TradeIQ
 
Loading...
Searching...
No Matches
json.hpp
Go to the documentation of this file.
1// __ _____ _____ _____
2// __| | __| | | | JSON for Modern C++
3// | | |__ | | | | | | version 3.12.0
4// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5//
6// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7// SPDX-License-Identifier: MIT
8
9/****************************************************************************\
10 * Note on documentation: The source files contain links to the online *
11 * documentation of the public API at https://json.nlohmann.me. This URL *
12 * contains the most recent documentation and should also be applicable to *
13 * previous versions; documentation for deprecated functions is not *
14 * removed, but marked deprecated. See "Generate documentation" section in *
15 * file docs/README.md. *
16\****************************************************************************/
17
18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
19#define INCLUDE_NLOHMANN_JSON_HPP_
20
21#include <algorithm> // all_of, find, for_each
22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
23#include <functional> // hash, less
24#include <initializer_list> // initializer_list
25#ifndef JSON_NO_IO
26 #include <iosfwd> // istream, ostream
27#endif // JSON_NO_IO
28#include <iterator> // random_access_iterator_tag
29#include <memory> // unique_ptr
30#include <string> // string, stoi, to_string
31#include <utility> // declval, forward, move, pair, swap
32#include <vector> // vector
33
34// #include <nlohmann/adl_serializer.hpp>
35// __ _____ _____ _____
36// __| | __| | | | JSON for Modern C++
37// | | |__ | | | | | | version 3.12.0
38// |_____|_____|_____|_|___| https://github.com/nlohmann/json
39//
40// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
41// SPDX-License-Identifier: MIT
42
43
44
45#include <utility>
46
47// #include <nlohmann/detail/abi_macros.hpp>
48// __ _____ _____ _____
49// __| | __| | | | JSON for Modern C++
50// | | |__ | | | | | | version 3.12.0
51// |_____|_____|_____|_|___| https://github.com/nlohmann/json
52//
53// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
54// SPDX-License-Identifier: MIT
55
56
57
58// This file contains all macro definitions affecting or depending on the ABI
59
60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
61 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
62 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
63 #warning "Already included a different version of the library!"
64 #endif
65 #endif
66#endif
67
68#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
69#define NLOHMANN_JSON_VERSION_MINOR 12 // NOLINT(modernize-macro-to-enum)
70#define NLOHMANN_JSON_VERSION_PATCH 0 // NOLINT(modernize-macro-to-enum)
71
72#ifndef JSON_DIAGNOSTICS
73 #define JSON_DIAGNOSTICS 0
74#endif
75
76#ifndef JSON_DIAGNOSTIC_POSITIONS
77 #define JSON_DIAGNOSTIC_POSITIONS 0
78#endif
79
80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
81 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
82#endif
83
84#if JSON_DIAGNOSTICS
85 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
86#else
87 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
88#endif
89
90#if JSON_DIAGNOSTIC_POSITIONS
91 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
92#else
93 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
94#endif
95
96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
97 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
98#else
99 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
100#endif
101
102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
103 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
104#endif
105
106// Construct the namespace ABI tags component
107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
108#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
109 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
110
111#define NLOHMANN_JSON_ABI_TAGS \
112 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
113 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
114 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
115 NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
116
117// Construct the namespace version component
118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
119 _v ## major ## _ ## minor ## _ ## patch
120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
121 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
122
123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
124#define NLOHMANN_JSON_NAMESPACE_VERSION
125#else
126#define NLOHMANN_JSON_NAMESPACE_VERSION \
127 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
128 NLOHMANN_JSON_VERSION_MINOR, \
129 NLOHMANN_JSON_VERSION_PATCH)
130#endif
131
132// Combine namespace components
133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
134#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
135 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
136
137#ifndef NLOHMANN_JSON_NAMESPACE
138#define NLOHMANN_JSON_NAMESPACE \
139 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
140 NLOHMANN_JSON_ABI_TAGS, \
141 NLOHMANN_JSON_NAMESPACE_VERSION)
142#endif
143
144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
145#define NLOHMANN_JSON_NAMESPACE_BEGIN \
146 namespace nlohmann \
147 { \
148 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
149 NLOHMANN_JSON_ABI_TAGS, \
150 NLOHMANN_JSON_NAMESPACE_VERSION) \
151 {
152#endif
153
154#ifndef NLOHMANN_JSON_NAMESPACE_END
155#define NLOHMANN_JSON_NAMESPACE_END \
156 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
157 } // namespace nlohmann
158#endif
159
160// #include <nlohmann/detail/conversions/from_json.hpp>
161// __ _____ _____ _____
162// __| | __| | | | JSON for Modern C++
163// | | |__ | | | | | | version 3.12.0
164// |_____|_____|_____|_|___| https://github.com/nlohmann/json
165//
166// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
167// SPDX-License-Identifier: MIT
168
169
170
171#include <algorithm> // transform
172#include <array> // array
173#include <forward_list> // forward_list
174#include <iterator> // inserter, front_inserter, end
175#include <map> // map
176#include <string> // string
177#include <tuple> // tuple, make_tuple
178#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
179#include <unordered_map> // unordered_map
180#include <utility> // pair, declval
181#include <valarray> // valarray
182
183// #include <nlohmann/detail/exceptions.hpp>
184// __ _____ _____ _____
185// __| | __| | | | JSON for Modern C++
186// | | |__ | | | | | | version 3.12.0
187// |_____|_____|_____|_|___| https://github.com/nlohmann/json
188//
189// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
190// SPDX-License-Identifier: MIT
191
192
193
194#include <cstddef> // nullptr_t
195#include <exception> // exception
196#if JSON_DIAGNOSTICS
197 #include <numeric> // accumulate
198#endif
199#include <stdexcept> // runtime_error
200#include <string> // to_string
201#include <vector> // vector
202
203// #include <nlohmann/detail/value_t.hpp>
204// __ _____ _____ _____
205// __| | __| | | | JSON for Modern C++
206// | | |__ | | | | | | version 3.12.0
207// |_____|_____|_____|_|___| https://github.com/nlohmann/json
208//
209// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
210// SPDX-License-Identifier: MIT
211
212
213
214#include <array> // array
215#include <cstddef> // size_t
216#include <cstdint> // uint8_t
217#include <string> // string
218
219// #include <nlohmann/detail/macro_scope.hpp>
220// __ _____ _____ _____
221// __| | __| | | | JSON for Modern C++
222// | | |__ | | | | | | version 3.12.0
223// |_____|_____|_____|_|___| https://github.com/nlohmann/json
224//
225// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
226// SPDX-License-Identifier: MIT
227
228
229
230#include <utility> // declval, pair
231// #include <nlohmann/detail/meta/detected.hpp>
232// __ _____ _____ _____
233// __| | __| | | | JSON for Modern C++
234// | | |__ | | | | | | version 3.12.0
235// |_____|_____|_____|_|___| https://github.com/nlohmann/json
236//
237// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
238// SPDX-License-Identifier: MIT
239
240
241
242#include <type_traits>
243
244// #include <nlohmann/detail/meta/void_t.hpp>
245// __ _____ _____ _____
246// __| | __| | | | JSON for Modern C++
247// | | |__ | | | | | | version 3.12.0
248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
249//
250// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
251// SPDX-License-Identifier: MIT
252
253
254
255// #include <nlohmann/detail/abi_macros.hpp>
256
257
259namespace detail
260{
261
262template<typename ...Ts> struct make_void
263{
264 using type = void;
265};
266template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
267
268} // namespace detail
270
271
273namespace detail
274{
275
276// https://en.cppreference.com/w/cpp/experimental/is_detected
278{
279 nonesuch() = delete;
280 ~nonesuch() = delete;
281 nonesuch(nonesuch const&) = delete;
282 nonesuch(nonesuch const&&) = delete;
283 void operator=(nonesuch const&) = delete;
284 void operator=(nonesuch&&) = delete;
285};
286
287template<class Default,
288 class AlwaysVoid,
289 template<class...> class Op,
290 class... Args>
292{
293 using value_t = std::false_type;
294 using type = Default;
295};
296
297template<class Default, template<class...> class Op, class... Args>
298struct detector<Default, void_t<Op<Args...>>, Op, Args...>
299{
300 using value_t = std::true_type;
301 using type = Op<Args...>;
302};
303
304template<template<class...> class Op, class... Args>
305using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
306
307template<template<class...> class Op, class... Args>
308struct is_detected_lazy : is_detected<Op, Args...> { };
309
310template<template<class...> class Op, class... Args>
311using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
312
313template<class Default, template<class...> class Op, class... Args>
314using detected_or = detector<Default, void, Op, Args...>;
315
316template<class Default, template<class...> class Op, class... Args>
317using detected_or_t = typename detected_or<Default, Op, Args...>::type;
318
319template<class Expected, template<class...> class Op, class... Args>
320using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
321
322template<class To, template<class...> class Op, class... Args>
324 std::is_convertible<detected_t<Op, Args...>, To>;
325
326} // namespace detail
328
329// #include <nlohmann/thirdparty/hedley/hedley.hpp>
330
331
332// __ _____ _____ _____
333// __| | __| | | | JSON for Modern C++
334// | | |__ | | | | | | version 3.12.0
335// |_____|_____|_____|_|___| https://github.com/nlohmann/json
336//
337// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
338// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
339// SPDX-License-Identifier: MIT
340
341/* Hedley - https://nemequ.github.io/hedley
342 * Created by Evan Nemerson <evan@nemerson.com>
343 */
344
345#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
346#if defined(JSON_HEDLEY_VERSION)
347 #undef JSON_HEDLEY_VERSION
348#endif
349#define JSON_HEDLEY_VERSION 15
350
351#if defined(JSON_HEDLEY_STRINGIFY_EX)
352 #undef JSON_HEDLEY_STRINGIFY_EX
353#endif
354#define JSON_HEDLEY_STRINGIFY_EX(x) #x
355
356#if defined(JSON_HEDLEY_STRINGIFY)
357 #undef JSON_HEDLEY_STRINGIFY
358#endif
359#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
360
361#if defined(JSON_HEDLEY_CONCAT_EX)
362 #undef JSON_HEDLEY_CONCAT_EX
363#endif
364#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
365
366#if defined(JSON_HEDLEY_CONCAT)
367 #undef JSON_HEDLEY_CONCAT
368#endif
369#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
370
371#if defined(JSON_HEDLEY_CONCAT3_EX)
372 #undef JSON_HEDLEY_CONCAT3_EX
373#endif
374#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
375
376#if defined(JSON_HEDLEY_CONCAT3)
377 #undef JSON_HEDLEY_CONCAT3
378#endif
379#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
380
381#if defined(JSON_HEDLEY_VERSION_ENCODE)
382 #undef JSON_HEDLEY_VERSION_ENCODE
383#endif
384#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
385
386#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
387 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
388#endif
389#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
390
391#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
392 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
393#endif
394#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
395
396#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
397 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
398#endif
399#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
400
401#if defined(JSON_HEDLEY_GNUC_VERSION)
402 #undef JSON_HEDLEY_GNUC_VERSION
403#endif
404#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
405 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
406#elif defined(__GNUC__)
407 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
408#endif
409
410#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
411 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
412#endif
413#if defined(JSON_HEDLEY_GNUC_VERSION)
414 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
415#else
416 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
417#endif
418
419#if defined(JSON_HEDLEY_MSVC_VERSION)
420 #undef JSON_HEDLEY_MSVC_VERSION
421#endif
422#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
423 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
424#elif defined(_MSC_FULL_VER) && !defined(__ICL)
425 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
426#elif defined(_MSC_VER) && !defined(__ICL)
427 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
428#endif
429
430#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
431 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
432#endif
433#if !defined(JSON_HEDLEY_MSVC_VERSION)
434 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
435#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
436 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
437#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
438 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
439#else
440 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
441#endif
442
443#if defined(JSON_HEDLEY_INTEL_VERSION)
444 #undef JSON_HEDLEY_INTEL_VERSION
445#endif
446#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
447 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
448#elif defined(__INTEL_COMPILER) && !defined(__ICL)
449 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
450#endif
451
452#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
453 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
454#endif
455#if defined(JSON_HEDLEY_INTEL_VERSION)
456 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
457#else
458 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
459#endif
460
461#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
462 #undef JSON_HEDLEY_INTEL_CL_VERSION
463#endif
464#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
465 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
466#endif
467
468#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
469 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
470#endif
471#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
472 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
473#else
474 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
475#endif
476
477#if defined(JSON_HEDLEY_PGI_VERSION)
478 #undef JSON_HEDLEY_PGI_VERSION
479#endif
480#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
481 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
482#endif
483
484#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
485 #undef JSON_HEDLEY_PGI_VERSION_CHECK
486#endif
487#if defined(JSON_HEDLEY_PGI_VERSION)
488 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
489#else
490 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
491#endif
492
493#if defined(JSON_HEDLEY_SUNPRO_VERSION)
494 #undef JSON_HEDLEY_SUNPRO_VERSION
495#endif
496#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
497 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
498#elif defined(__SUNPRO_C)
499 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
500#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
501 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
502#elif defined(__SUNPRO_CC)
503 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
504#endif
505
506#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
507 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
508#endif
509#if defined(JSON_HEDLEY_SUNPRO_VERSION)
510 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
511#else
512 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
513#endif
514
515#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
516 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
517#endif
518#if defined(__EMSCRIPTEN__)
519 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
520#endif
521
522#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
523 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
524#endif
525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
526 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
527#else
528 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
529#endif
530
531#if defined(JSON_HEDLEY_ARM_VERSION)
532 #undef JSON_HEDLEY_ARM_VERSION
533#endif
534#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
535 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
536#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
537 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
538#endif
539
540#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
541 #undef JSON_HEDLEY_ARM_VERSION_CHECK
542#endif
543#if defined(JSON_HEDLEY_ARM_VERSION)
544 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
545#else
546 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
547#endif
548
549#if defined(JSON_HEDLEY_IBM_VERSION)
550 #undef JSON_HEDLEY_IBM_VERSION
551#endif
552#if defined(__ibmxl__)
553 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
554#elif defined(__xlC__) && defined(__xlC_ver__)
555 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
556#elif defined(__xlC__)
557 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
558#endif
559
560#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
561 #undef JSON_HEDLEY_IBM_VERSION_CHECK
562#endif
563#if defined(JSON_HEDLEY_IBM_VERSION)
564 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
565#else
566 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
567#endif
568
569#if defined(JSON_HEDLEY_TI_VERSION)
570 #undef JSON_HEDLEY_TI_VERSION
571#endif
572#if \
573 defined(__TI_COMPILER_VERSION__) && \
574 ( \
575 defined(__TMS470__) || defined(__TI_ARM__) || \
576 defined(__MSP430__) || \
577 defined(__TMS320C2000__) \
578 )
579#if (__TI_COMPILER_VERSION__ >= 16000000)
580 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
581#endif
582#endif
583
584#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
585 #undef JSON_HEDLEY_TI_VERSION_CHECK
586#endif
587#if defined(JSON_HEDLEY_TI_VERSION)
588 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
589#else
590 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
591#endif
592
593#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
594 #undef JSON_HEDLEY_TI_CL2000_VERSION
595#endif
596#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
597 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
598#endif
599
600#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
601 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
602#endif
603#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
604 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
605#else
606 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
607#endif
608
609#if defined(JSON_HEDLEY_TI_CL430_VERSION)
610 #undef JSON_HEDLEY_TI_CL430_VERSION
611#endif
612#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
613 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
614#endif
615
616#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
617 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
618#endif
619#if defined(JSON_HEDLEY_TI_CL430_VERSION)
620 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
621#else
622 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
623#endif
624
625#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
626 #undef JSON_HEDLEY_TI_ARMCL_VERSION
627#endif
628#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
629 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
630#endif
631
632#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
633 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
634#endif
635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
636 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
637#else
638 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
639#endif
640
641#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
642 #undef JSON_HEDLEY_TI_CL6X_VERSION
643#endif
644#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
645 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
646#endif
647
648#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
649 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
650#endif
651#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
652 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
653#else
654 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
655#endif
656
657#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
658 #undef JSON_HEDLEY_TI_CL7X_VERSION
659#endif
660#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
661 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
662#endif
663
664#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
665 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
666#endif
667#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
668 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
669#else
670 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
671#endif
672
673#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
674 #undef JSON_HEDLEY_TI_CLPRU_VERSION
675#endif
676#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
677 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
678#endif
679
680#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
681 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
682#endif
683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
684 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
685#else
686 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
687#endif
688
689#if defined(JSON_HEDLEY_CRAY_VERSION)
690 #undef JSON_HEDLEY_CRAY_VERSION
691#endif
692#if defined(_CRAYC)
693 #if defined(_RELEASE_PATCHLEVEL)
694 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
695 #else
696 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
697 #endif
698#endif
699
700#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
701 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
702#endif
703#if defined(JSON_HEDLEY_CRAY_VERSION)
704 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
705#else
706 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
707#endif
708
709#if defined(JSON_HEDLEY_IAR_VERSION)
710 #undef JSON_HEDLEY_IAR_VERSION
711#endif
712#if defined(__IAR_SYSTEMS_ICC__)
713 #if __VER__ > 1000
714 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
715 #else
716 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
717 #endif
718#endif
719
720#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
721 #undef JSON_HEDLEY_IAR_VERSION_CHECK
722#endif
723#if defined(JSON_HEDLEY_IAR_VERSION)
724 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
725#else
726 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
727#endif
728
729#if defined(JSON_HEDLEY_TINYC_VERSION)
730 #undef JSON_HEDLEY_TINYC_VERSION
731#endif
732#if defined(__TINYC__)
733 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
734#endif
735
736#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
737 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
738#endif
739#if defined(JSON_HEDLEY_TINYC_VERSION)
740 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
741#else
742 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
743#endif
744
745#if defined(JSON_HEDLEY_DMC_VERSION)
746 #undef JSON_HEDLEY_DMC_VERSION
747#endif
748#if defined(__DMC__)
749 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
750#endif
751
752#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
753 #undef JSON_HEDLEY_DMC_VERSION_CHECK
754#endif
755#if defined(JSON_HEDLEY_DMC_VERSION)
756 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
757#else
758 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
759#endif
760
761#if defined(JSON_HEDLEY_COMPCERT_VERSION)
762 #undef JSON_HEDLEY_COMPCERT_VERSION
763#endif
764#if defined(__COMPCERT_VERSION__)
765 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
766#endif
767
768#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
769 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
770#endif
771#if defined(JSON_HEDLEY_COMPCERT_VERSION)
772 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
773#else
774 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
775#endif
776
777#if defined(JSON_HEDLEY_PELLES_VERSION)
778 #undef JSON_HEDLEY_PELLES_VERSION
779#endif
780#if defined(__POCC__)
781 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
782#endif
783
784#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
785 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
786#endif
787#if defined(JSON_HEDLEY_PELLES_VERSION)
788 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
789#else
790 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
791#endif
792
793#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
794 #undef JSON_HEDLEY_MCST_LCC_VERSION
795#endif
796#if defined(__LCC__) && defined(__LCC_MINOR__)
797 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
798#endif
799
800#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
801 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
802#endif
803#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
804 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
805#else
806 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
807#endif
808
809#if defined(JSON_HEDLEY_GCC_VERSION)
810 #undef JSON_HEDLEY_GCC_VERSION
811#endif
812#if \
813 defined(JSON_HEDLEY_GNUC_VERSION) && \
814 !defined(__clang__) && \
815 !defined(JSON_HEDLEY_INTEL_VERSION) && \
816 !defined(JSON_HEDLEY_PGI_VERSION) && \
817 !defined(JSON_HEDLEY_ARM_VERSION) && \
818 !defined(JSON_HEDLEY_CRAY_VERSION) && \
819 !defined(JSON_HEDLEY_TI_VERSION) && \
820 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
821 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
822 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
823 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
826 !defined(__COMPCERT__) && \
827 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
828 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
829#endif
830
831#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
832 #undef JSON_HEDLEY_GCC_VERSION_CHECK
833#endif
834#if defined(JSON_HEDLEY_GCC_VERSION)
835 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
836#else
837 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
838#endif
839
840#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
841 #undef JSON_HEDLEY_HAS_ATTRIBUTE
842#endif
843#if \
844 defined(__has_attribute) && \
845 ( \
846 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
847 )
848# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
849#else
850# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
851#endif
852
853#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
854 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
855#endif
856#if defined(__has_attribute)
857 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
858#else
859 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
860#endif
861
862#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
863 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
864#endif
865#if defined(__has_attribute)
866 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
867#else
868 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
869#endif
870
871#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
872 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
873#endif
874#if \
875 defined(__has_cpp_attribute) && \
876 defined(__cplusplus) && \
877 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
878 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
879#else
880 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
881#endif
882
883#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
884 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
885#endif
886#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
887 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
888#elif \
889 !defined(JSON_HEDLEY_PGI_VERSION) && \
890 !defined(JSON_HEDLEY_IAR_VERSION) && \
891 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
892 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
893 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
894#else
895 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
896#endif
897
898#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
899 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
900#endif
901#if defined(__has_cpp_attribute) && defined(__cplusplus)
902 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
903#else
904 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
905#endif
906
907#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
908 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
909#endif
910#if defined(__has_cpp_attribute) && defined(__cplusplus)
911 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
912#else
913 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
914#endif
915
916#if defined(JSON_HEDLEY_HAS_BUILTIN)
917 #undef JSON_HEDLEY_HAS_BUILTIN
918#endif
919#if defined(__has_builtin)
920 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
921#else
922 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
923#endif
924
925#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
926 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
927#endif
928#if defined(__has_builtin)
929 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
930#else
931 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
932#endif
933
934#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
935 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
936#endif
937#if defined(__has_builtin)
938 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
939#else
940 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
941#endif
942
943#if defined(JSON_HEDLEY_HAS_FEATURE)
944 #undef JSON_HEDLEY_HAS_FEATURE
945#endif
946#if defined(__has_feature)
947 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
948#else
949 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
950#endif
951
952#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
953 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
954#endif
955#if defined(__has_feature)
956 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
957#else
958 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
959#endif
960
961#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
962 #undef JSON_HEDLEY_GCC_HAS_FEATURE
963#endif
964#if defined(__has_feature)
965 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
966#else
967 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
968#endif
969
970#if defined(JSON_HEDLEY_HAS_EXTENSION)
971 #undef JSON_HEDLEY_HAS_EXTENSION
972#endif
973#if defined(__has_extension)
974 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
975#else
976 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
977#endif
978
979#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
980 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
981#endif
982#if defined(__has_extension)
983 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
984#else
985 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
986#endif
987
988#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
989 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
990#endif
991#if defined(__has_extension)
992 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
993#else
994 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
995#endif
996
997#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
998 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
999#endif
1000#if defined(__has_declspec_attribute)
1001 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1002#else
1003 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1004#endif
1005
1006#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1007 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1008#endif
1009#if defined(__has_declspec_attribute)
1010 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1011#else
1012 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1013#endif
1014
1015#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1016 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1017#endif
1018#if defined(__has_declspec_attribute)
1019 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1020#else
1021 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1022#endif
1023
1024#if defined(JSON_HEDLEY_HAS_WARNING)
1025 #undef JSON_HEDLEY_HAS_WARNING
1026#endif
1027#if defined(__has_warning)
1028 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1029#else
1030 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1031#endif
1032
1033#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1034 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1035#endif
1036#if defined(__has_warning)
1037 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1038#else
1039 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1040#endif
1041
1042#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1043 #undef JSON_HEDLEY_GCC_HAS_WARNING
1044#endif
1045#if defined(__has_warning)
1046 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1047#else
1048 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1049#endif
1050
1051#if \
1052 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1053 defined(__clang__) || \
1054 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1055 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1056 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1057 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1058 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1059 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1060 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1061 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1062 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1063 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1064 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1065 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1066 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1067 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1068 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1069 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1070 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1071#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1072 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1073#else
1074 #define JSON_HEDLEY_PRAGMA(value)
1075#endif
1076
1077#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1078 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1079#endif
1080#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1081 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1082#endif
1083#if defined(__clang__)
1084 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1085 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1086#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1089#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1090 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1091 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1092#elif \
1093 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1094 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1095 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1096 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1097#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1098 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1099 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1100#elif \
1101 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1102 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1103 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1104 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1105 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1106 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1107 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1108 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1109#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1110 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1111 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1112#else
1113 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1114 #define JSON_HEDLEY_DIAGNOSTIC_POP
1115#endif
1116
1117/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1118 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1119#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1120 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1121#endif
1122#if defined(__cplusplus)
1123# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1124# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1125# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1126# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1127 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1128 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1129 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1130 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1131 xpr \
1132 JSON_HEDLEY_DIAGNOSTIC_POP
1133# else
1134# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1135 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1136 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1137 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1138 xpr \
1139 JSON_HEDLEY_DIAGNOSTIC_POP
1140# endif
1141# else
1142# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1143 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1144 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1145 xpr \
1146 JSON_HEDLEY_DIAGNOSTIC_POP
1147# endif
1148# endif
1149#endif
1150#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1151 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1152#endif
1153
1154#if defined(JSON_HEDLEY_CONST_CAST)
1155 #undef JSON_HEDLEY_CONST_CAST
1156#endif
1157#if defined(__cplusplus)
1158# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1159#elif \
1160 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1161 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1162 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1163# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1164 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1165 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1166 ((T) (expr)); \
1167 JSON_HEDLEY_DIAGNOSTIC_POP \
1168 }))
1169#else
1170# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1171#endif
1172
1173#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1174 #undef JSON_HEDLEY_REINTERPRET_CAST
1175#endif
1176#if defined(__cplusplus)
1177 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1178#else
1179 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1180#endif
1181
1182#if defined(JSON_HEDLEY_STATIC_CAST)
1183 #undef JSON_HEDLEY_STATIC_CAST
1184#endif
1185#if defined(__cplusplus)
1186 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1187#else
1188 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1189#endif
1190
1191#if defined(JSON_HEDLEY_CPP_CAST)
1192 #undef JSON_HEDLEY_CPP_CAST
1193#endif
1194#if defined(__cplusplus)
1195# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1196# define JSON_HEDLEY_CPP_CAST(T, expr) \
1197 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1198 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1199 ((T) (expr)) \
1200 JSON_HEDLEY_DIAGNOSTIC_POP
1201# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1202# define JSON_HEDLEY_CPP_CAST(T, expr) \
1203 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1204 _Pragma("diag_suppress=Pe137") \
1205 JSON_HEDLEY_DIAGNOSTIC_POP
1206# else
1207# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1208# endif
1209#else
1210# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1211#endif
1212
1213#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1214 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1215#endif
1216#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1217 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1218#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1219 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1220#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1221 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1222#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1223 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1224#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1225 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1226#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1227 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1228#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1229 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1230#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1231 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1232#elif \
1233 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1234 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1235 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1236 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1237 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1238 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1239 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1240 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1241 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1242 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1243 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1244 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1245#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1246 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1247#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1248 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1249#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1250 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1251#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1252 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1253#else
1254 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1255#endif
1256
1257#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1258 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1259#endif
1260#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1261 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1262#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1263 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1264#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1265 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1266#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1267 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1268#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1269 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1270#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1271 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1272#elif \
1273 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1274 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1275 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1276 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1277 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1278#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1279 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1280#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1281 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1282#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1283 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1284#else
1285 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1286#endif
1287
1288#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1289 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1290#endif
1291#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1292 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1293#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1294 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1295#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1296 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1297#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1298 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1299#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1300 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1301#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1302 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1303#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1304 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1305#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1306 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1307#elif \
1308 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1309 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1310 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1311 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1312#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1313 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1314#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1315 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1316#else
1317 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1318#endif
1319
1320#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1321 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1322#endif
1323#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1324 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1325#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1326 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1327#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1328 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1329#else
1330 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1331#endif
1332
1333#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1334 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1335#endif
1336#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1337 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1338#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1339 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1340#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1341 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1342#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1343 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1344#else
1345 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1346#endif
1347
1348#if defined(JSON_HEDLEY_DEPRECATED)
1349 #undef JSON_HEDLEY_DEPRECATED
1350#endif
1351#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1352 #undef JSON_HEDLEY_DEPRECATED_FOR
1353#endif
1354#if \
1355 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1356 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1357 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1358 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1359#elif \
1360 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1361 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1362 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1363 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1364 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1365 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1366 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1367 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1368 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1369 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1370 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1371 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1372 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1373 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1374#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1375 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1376 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1377#elif \
1378 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1379 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1380 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1381 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1382 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1383 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1384 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1385 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1386 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1387 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1388 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1389 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1390 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1391 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1392 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1393 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1394 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1395 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1396#elif \
1397 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1398 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1399 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1400 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1401 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1402#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1403 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1404 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1405#else
1406 #define JSON_HEDLEY_DEPRECATED(since)
1407 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1408#endif
1409
1410#if defined(JSON_HEDLEY_UNAVAILABLE)
1411 #undef JSON_HEDLEY_UNAVAILABLE
1412#endif
1413#if \
1414 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1415 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1416 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1417 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1418 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1419#else
1420 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1421#endif
1422
1423#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1424 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1425#endif
1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1427 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1428#endif
1429#if \
1430 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1431 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1432 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1433 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1434 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1435 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1436 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1437 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1438 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1439 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1440 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1441 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1442 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1443 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1444 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1445 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1446 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1447 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1448 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1449#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1451 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1452#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1454 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1455#elif defined(_Check_return_) /* SAL */
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1457 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1458#else
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1461#endif
1462
1463#if defined(JSON_HEDLEY_SENTINEL)
1464 #undef JSON_HEDLEY_SENTINEL
1465#endif
1466#if \
1467 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1468 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1469 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1470 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1471 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1472 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1473#else
1474 #define JSON_HEDLEY_SENTINEL(position)
1475#endif
1476
1477#if defined(JSON_HEDLEY_NO_RETURN)
1478 #undef JSON_HEDLEY_NO_RETURN
1479#endif
1480#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1481 #define JSON_HEDLEY_NO_RETURN __noreturn
1482#elif \
1483 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1484 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1485 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1486#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1487 #define JSON_HEDLEY_NO_RETURN _Noreturn
1488#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1489 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1490#elif \
1491 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1492 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1493 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1494 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1495 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1496 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1497 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1498 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1499 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1500 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1501 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1502 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1503 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1504 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1505 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1506 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1507 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1508 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1509#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1510 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1511#elif \
1512 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1513 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1514 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1515#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1516 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1517#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1518 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1519#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1520 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1521#else
1522 #define JSON_HEDLEY_NO_RETURN
1523#endif
1524
1525#if defined(JSON_HEDLEY_NO_ESCAPE)
1526 #undef JSON_HEDLEY_NO_ESCAPE
1527#endif
1528#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1529 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1530#else
1531 #define JSON_HEDLEY_NO_ESCAPE
1532#endif
1533
1534#if defined(JSON_HEDLEY_UNREACHABLE)
1535 #undef JSON_HEDLEY_UNREACHABLE
1536#endif
1537#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1538 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1539#endif
1540#if defined(JSON_HEDLEY_ASSUME)
1541 #undef JSON_HEDLEY_ASSUME
1542#endif
1543#if \
1544 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1545 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1546 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1547 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1548#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1549 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1550#elif \
1551 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1552 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1553 #if defined(__cplusplus)
1554 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1555 #else
1556 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1557 #endif
1558#endif
1559#if \
1560 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1561 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1562 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1563 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1564 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1565 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1566 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1567 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1568#elif defined(JSON_HEDLEY_ASSUME)
1569 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1570#endif
1571#if !defined(JSON_HEDLEY_ASSUME)
1572 #if defined(JSON_HEDLEY_UNREACHABLE)
1573 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1574 #else
1575 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1576 #endif
1577#endif
1578#if defined(JSON_HEDLEY_UNREACHABLE)
1579 #if \
1580 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1581 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1582 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1583 #else
1584 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1585 #endif
1586#else
1587 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1588#endif
1589#if !defined(JSON_HEDLEY_UNREACHABLE)
1590 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1591#endif
1592
1594#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1595 #pragma clang diagnostic ignored "-Wpedantic"
1596#endif
1597#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1598 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1599#endif
1600#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1601 #if defined(__clang__)
1602 #pragma clang diagnostic ignored "-Wvariadic-macros"
1603 #elif defined(JSON_HEDLEY_GCC_VERSION)
1604 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1605 #endif
1606#endif
1607#if defined(JSON_HEDLEY_NON_NULL)
1608 #undef JSON_HEDLEY_NON_NULL
1609#endif
1610#if \
1611 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1612 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1613 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1614 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1615 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1616#else
1617 #define JSON_HEDLEY_NON_NULL(...)
1618#endif
1620
1621#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1622 #undef JSON_HEDLEY_PRINTF_FORMAT
1623#endif
1624#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1625 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1626#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1627 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1628#elif \
1629 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1630 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1631 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1632 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1633 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1634 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1635 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1636 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1637 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1638 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1639 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1640 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1641 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1642 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1643 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1644 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1645 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1646 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1647#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1648 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1649#else
1650 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1651#endif
1652
1653#if defined(JSON_HEDLEY_CONSTEXPR)
1654 #undef JSON_HEDLEY_CONSTEXPR
1655#endif
1656#if defined(__cplusplus)
1657 #if __cplusplus >= 201103L
1658 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1659 #endif
1660#endif
1661#if !defined(JSON_HEDLEY_CONSTEXPR)
1662 #define JSON_HEDLEY_CONSTEXPR
1663#endif
1664
1665#if defined(JSON_HEDLEY_PREDICT)
1666 #undef JSON_HEDLEY_PREDICT
1667#endif
1668#if defined(JSON_HEDLEY_LIKELY)
1669 #undef JSON_HEDLEY_LIKELY
1670#endif
1671#if defined(JSON_HEDLEY_UNLIKELY)
1672 #undef JSON_HEDLEY_UNLIKELY
1673#endif
1674#if defined(JSON_HEDLEY_UNPREDICTABLE)
1675 #undef JSON_HEDLEY_UNPREDICTABLE
1676#endif
1677#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1678 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1679#endif
1680#if \
1681 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1682 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1683 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1684# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1685# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1686# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1687# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1688# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1689#elif \
1690 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1691 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1692 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1693 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1694 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1695 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1696 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1697 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1698 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1699 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1700 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1701 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1702 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1703 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1704 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1705 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1706# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1707 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1708# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1709 (__extension__ ({ \
1710 double hedley_probability_ = (probability); \
1711 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1712 }))
1713# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1714 (__extension__ ({ \
1715 double hedley_probability_ = (probability); \
1716 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1717 }))
1718# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1719# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1720#else
1721# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1722# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1723# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1724# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1725# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1726#endif
1727#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1728 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1729#endif
1730
1731#if defined(JSON_HEDLEY_MALLOC)
1732 #undef JSON_HEDLEY_MALLOC
1733#endif
1734#if \
1735 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1736 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1737 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1738 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1739 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1740 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1741 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1742 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1743 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1744 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1745 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1746 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1747 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1748 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1749 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1750 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1751 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1752 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1753 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1754#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1755 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1756#elif \
1757 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1758 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1759 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1760#else
1761 #define JSON_HEDLEY_MALLOC
1762#endif
1763
1764#if defined(JSON_HEDLEY_PURE)
1765 #undef JSON_HEDLEY_PURE
1766#endif
1767#if \
1768 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1769 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1770 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1771 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1772 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1773 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1774 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1775 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1776 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1777 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1778 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1779 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1780 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1781 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1782 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1783 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1784 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1785 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1786 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1787# define JSON_HEDLEY_PURE __attribute__((__pure__))
1788#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1789# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1790#elif defined(__cplusplus) && \
1791 ( \
1792 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1793 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1794 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1795 )
1796# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1797#else
1798# define JSON_HEDLEY_PURE
1799#endif
1800
1801#if defined(JSON_HEDLEY_CONST)
1802 #undef JSON_HEDLEY_CONST
1803#endif
1804#if \
1805 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1806 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1807 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1808 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1809 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1810 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1811 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1812 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1813 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1814 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1815 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1816 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1817 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1818 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1819 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1820 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1821 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1822 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1823 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1824 #define JSON_HEDLEY_CONST __attribute__((__const__))
1825#elif \
1826 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1827 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1828#else
1829 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1830#endif
1831
1832#if defined(JSON_HEDLEY_RESTRICT)
1833 #undef JSON_HEDLEY_RESTRICT
1834#endif
1835#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1836 #define JSON_HEDLEY_RESTRICT restrict
1837#elif \
1838 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1839 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1840 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1841 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1842 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1843 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1844 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1845 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1846 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1847 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1848 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1849 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1850 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1851 defined(__clang__) || \
1852 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1853 #define JSON_HEDLEY_RESTRICT __restrict
1854#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1855 #define JSON_HEDLEY_RESTRICT _Restrict
1856#else
1857 #define JSON_HEDLEY_RESTRICT
1858#endif
1859
1860#if defined(JSON_HEDLEY_INLINE)
1861 #undef JSON_HEDLEY_INLINE
1862#endif
1863#if \
1864 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1865 (defined(__cplusplus) && (__cplusplus >= 199711L))
1866 #define JSON_HEDLEY_INLINE inline
1867#elif \
1868 defined(JSON_HEDLEY_GCC_VERSION) || \
1869 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1870 #define JSON_HEDLEY_INLINE __inline__
1871#elif \
1872 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1873 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1874 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1875 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1876 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1877 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1878 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1879 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1880 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1881 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1882 #define JSON_HEDLEY_INLINE __inline
1883#else
1884 #define JSON_HEDLEY_INLINE
1885#endif
1886
1887#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1888 #undef JSON_HEDLEY_ALWAYS_INLINE
1889#endif
1890#if \
1891 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1892 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1893 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1894 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1895 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1896 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1897 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1898 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1899 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1900 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1901 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1902 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1903 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1904 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1905 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1906 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1907 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1908 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1909 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1910# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1911#elif \
1912 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1913 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1914# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1915#elif defined(__cplusplus) && \
1916 ( \
1917 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1918 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1919 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1920 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1921 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1922 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1923 )
1924# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1925#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1926# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1927#else
1928# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1929#endif
1930
1931#if defined(JSON_HEDLEY_NEVER_INLINE)
1932 #undef JSON_HEDLEY_NEVER_INLINE
1933#endif
1934#if \
1935 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1936 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1937 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1938 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1939 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1940 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1941 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1942 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1943 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1944 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1945 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1946 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1947 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1948 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1949 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1950 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1951 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1952 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1953 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1954 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1955#elif \
1956 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1957 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1958 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1959#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1960 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1961#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1962 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1963#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1964 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1965#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1966 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1967#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1968 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1969#else
1970 #define JSON_HEDLEY_NEVER_INLINE
1971#endif
1972
1973#if defined(JSON_HEDLEY_PRIVATE)
1974 #undef JSON_HEDLEY_PRIVATE
1975#endif
1976#if defined(JSON_HEDLEY_PUBLIC)
1977 #undef JSON_HEDLEY_PUBLIC
1978#endif
1979#if defined(JSON_HEDLEY_IMPORT)
1980 #undef JSON_HEDLEY_IMPORT
1981#endif
1982#if defined(_WIN32) || defined(__CYGWIN__)
1983# define JSON_HEDLEY_PRIVATE
1984# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1985# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1986#else
1987# if \
1988 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1989 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1990 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1991 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1992 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1993 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1994 ( \
1995 defined(__TI_EABI__) && \
1996 ( \
1997 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1998 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
1999 ) \
2000 ) || \
2001 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2002# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2003# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2004# else
2005# define JSON_HEDLEY_PRIVATE
2006# define JSON_HEDLEY_PUBLIC
2007# endif
2008# define JSON_HEDLEY_IMPORT extern
2009#endif
2010
2011#if defined(JSON_HEDLEY_NO_THROW)
2012 #undef JSON_HEDLEY_NO_THROW
2013#endif
2014#if \
2015 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2016 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2017 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2018 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2019 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2020#elif \
2021 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2022 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2023 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2024 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2025#else
2026 #define JSON_HEDLEY_NO_THROW
2027#endif
2028
2029#if defined(JSON_HEDLEY_FALL_THROUGH)
2030 #undef JSON_HEDLEY_FALL_THROUGH
2031#endif
2032#if \
2033 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2034 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2035 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2036 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2037#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2038 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2039#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2040 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2041#elif defined(__fallthrough) /* SAL */
2042 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2043#else
2044 #define JSON_HEDLEY_FALL_THROUGH
2045#endif
2046
2047#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2048 #undef JSON_HEDLEY_RETURNS_NON_NULL
2049#endif
2050#if \
2051 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2052 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2053 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2054 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2055#elif defined(_Ret_notnull_) /* SAL */
2056 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2057#else
2058 #define JSON_HEDLEY_RETURNS_NON_NULL
2059#endif
2060
2061#if defined(JSON_HEDLEY_ARRAY_PARAM)
2062 #undef JSON_HEDLEY_ARRAY_PARAM
2063#endif
2064#if \
2065 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2066 !defined(__STDC_NO_VLA__) && \
2067 !defined(__cplusplus) && \
2068 !defined(JSON_HEDLEY_PGI_VERSION) && \
2069 !defined(JSON_HEDLEY_TINYC_VERSION)
2070 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2071#else
2072 #define JSON_HEDLEY_ARRAY_PARAM(name)
2073#endif
2074
2075#if defined(JSON_HEDLEY_IS_CONSTANT)
2076 #undef JSON_HEDLEY_IS_CONSTANT
2077#endif
2078#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2079 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2080#endif
2081/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2082 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2083#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2084 #undef JSON_HEDLEY_IS_CONSTEXPR_
2085#endif
2086#if \
2087 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2088 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2089 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2090 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2091 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2092 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2093 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2094 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2095 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2096 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2097 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2098#endif
2099#if !defined(__cplusplus)
2100# if \
2101 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2102 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2103 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2104 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2105 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2106 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2107 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2108#if defined(__INTPTR_TYPE__)
2109 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2110#else
2111 #include <stdint.h>
2112 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2113#endif
2114# elif \
2115 ( \
2116 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2117 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2118 !defined(JSON_HEDLEY_PGI_VERSION) && \
2119 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2120 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2121 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2122 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2123 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2124 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2125#if defined(__INTPTR_TYPE__)
2126 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2127#else
2128 #include <stdint.h>
2129 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2130#endif
2131# elif \
2132 defined(JSON_HEDLEY_GCC_VERSION) || \
2133 defined(JSON_HEDLEY_INTEL_VERSION) || \
2134 defined(JSON_HEDLEY_TINYC_VERSION) || \
2135 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2136 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2137 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2138 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2139 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2140 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2141 defined(__clang__)
2142# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2143 sizeof(void) != \
2144 sizeof(*( \
2145 1 ? \
2146 ((void*) ((expr) * 0L) ) : \
2147((struct { char v[sizeof(void) * 2]; } *) 1) \
2148 ) \
2149 ) \
2150 )
2151# endif
2152#endif
2153#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2154 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2155 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2156 #endif
2157 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2158#else
2159 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2160 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2161 #endif
2162 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2163#endif
2164
2165#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2166 #undef JSON_HEDLEY_BEGIN_C_DECLS
2167#endif
2168#if defined(JSON_HEDLEY_END_C_DECLS)
2169 #undef JSON_HEDLEY_END_C_DECLS
2170#endif
2171#if defined(JSON_HEDLEY_C_DECL)
2172 #undef JSON_HEDLEY_C_DECL
2173#endif
2174#if defined(__cplusplus)
2175 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2176 #define JSON_HEDLEY_END_C_DECLS }
2177 #define JSON_HEDLEY_C_DECL extern "C"
2178#else
2179 #define JSON_HEDLEY_BEGIN_C_DECLS
2180 #define JSON_HEDLEY_END_C_DECLS
2181 #define JSON_HEDLEY_C_DECL
2182#endif
2183
2184#if defined(JSON_HEDLEY_STATIC_ASSERT)
2185 #undef JSON_HEDLEY_STATIC_ASSERT
2186#endif
2187#if \
2188 !defined(__cplusplus) && ( \
2189 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2190 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2191 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2192 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2193 defined(_Static_assert) \
2194 )
2195# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2196#elif \
2197 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2198 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2199 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2200# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2201#else
2202# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2203#endif
2204
2205#if defined(JSON_HEDLEY_NULL)
2206 #undef JSON_HEDLEY_NULL
2207#endif
2208#if defined(__cplusplus)
2209 #if __cplusplus >= 201103L
2210 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2211 #elif defined(NULL)
2212 #define JSON_HEDLEY_NULL NULL
2213 #else
2214 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2215 #endif
2216#elif defined(NULL)
2217 #define JSON_HEDLEY_NULL NULL
2218#else
2219 #define JSON_HEDLEY_NULL ((void*) 0)
2220#endif
2221
2222#if defined(JSON_HEDLEY_MESSAGE)
2223 #undef JSON_HEDLEY_MESSAGE
2224#endif
2225#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2226# define JSON_HEDLEY_MESSAGE(msg) \
2227 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2228 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2229 JSON_HEDLEY_PRAGMA(message msg) \
2230 JSON_HEDLEY_DIAGNOSTIC_POP
2231#elif \
2232 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2233 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2234# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2235#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2236# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2237#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2238# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2239#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2240# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2241#else
2242# define JSON_HEDLEY_MESSAGE(msg)
2243#endif
2244
2245#if defined(JSON_HEDLEY_WARNING)
2246 #undef JSON_HEDLEY_WARNING
2247#endif
2248#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2249# define JSON_HEDLEY_WARNING(msg) \
2250 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2251 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2252 JSON_HEDLEY_PRAGMA(clang warning msg) \
2253 JSON_HEDLEY_DIAGNOSTIC_POP
2254#elif \
2255 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2256 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2257 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2258# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2259#elif \
2260 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2261 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2262# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2263#else
2264# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2265#endif
2266
2267#if defined(JSON_HEDLEY_REQUIRE)
2268 #undef JSON_HEDLEY_REQUIRE
2269#endif
2270#if defined(JSON_HEDLEY_REQUIRE_MSG)
2271 #undef JSON_HEDLEY_REQUIRE_MSG
2272#endif
2273#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2274# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2275# define JSON_HEDLEY_REQUIRE(expr) \
2276 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2277 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2278 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2279 JSON_HEDLEY_DIAGNOSTIC_POP
2280# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2281 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2282 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2283 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2284 JSON_HEDLEY_DIAGNOSTIC_POP
2285# else
2286# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2287# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2288# endif
2289#else
2290# define JSON_HEDLEY_REQUIRE(expr)
2291# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2292#endif
2293
2294#if defined(JSON_HEDLEY_FLAGS)
2295 #undef JSON_HEDLEY_FLAGS
2296#endif
2297#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2298 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2299#else
2300 #define JSON_HEDLEY_FLAGS
2301#endif
2302
2303#if defined(JSON_HEDLEY_FLAGS_CAST)
2304 #undef JSON_HEDLEY_FLAGS_CAST
2305#endif
2306#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2307# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2308 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2309 _Pragma("warning(disable:188)") \
2310 ((T) (expr)); \
2311 JSON_HEDLEY_DIAGNOSTIC_POP \
2312 }))
2313#else
2314# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2315#endif
2316
2317#if defined(JSON_HEDLEY_EMPTY_BASES)
2318 #undef JSON_HEDLEY_EMPTY_BASES
2319#endif
2320#if \
2321 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2322 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2323 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2324#else
2325 #define JSON_HEDLEY_EMPTY_BASES
2326#endif
2327
2328/* Remaining macros are deprecated. */
2329
2330#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2331 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2332#endif
2333#if defined(__clang__)
2334 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2335#else
2336 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2337#endif
2338
2339#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2340 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2341#endif
2342#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2343
2344#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2345 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2346#endif
2347#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2348
2349#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2350 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2351#endif
2352#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2353
2354#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2355 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2356#endif
2357#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2358
2359#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2360 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2361#endif
2362#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2363
2364#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2365 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2366#endif
2367#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2368
2369#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2370 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2371#endif
2372#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2373
2374#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2375
2376
2377// This file contains all internal macro definitions (except those affecting ABI)
2378// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2379
2380// #include <nlohmann/detail/abi_macros.hpp>
2381
2382
2383// exclude unsupported compilers
2384#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2385 #if defined(__clang__)
2386 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2387 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2388 #endif
2389 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2390 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2391 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2392 #endif
2393 #endif
2394#endif
2395
2396// C++ language standard detection
2397// if the user manually specified the used C++ version, this is skipped
2398#if !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2399 #if (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
2400 #define JSON_HAS_CPP_23
2401 #define JSON_HAS_CPP_20
2402 #define JSON_HAS_CPP_17
2403 #define JSON_HAS_CPP_14
2404 #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
2405 #define JSON_HAS_CPP_20
2406 #define JSON_HAS_CPP_17
2407 #define JSON_HAS_CPP_14
2408 #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2409 #define JSON_HAS_CPP_17
2410 #define JSON_HAS_CPP_14
2411 #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2412 #define JSON_HAS_CPP_14
2413 #endif
2414 // the cpp 11 flag is always specified because it is the minimal required version
2415 #define JSON_HAS_CPP_11
2416#endif
2417
2418#ifdef __has_include
2419 #if __has_include(<version>)
2420 #include <version>
2421 #endif
2422#endif
2423
2424#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2425 #ifdef JSON_HAS_CPP_17
2426 #if defined(__cpp_lib_filesystem)
2427 #define JSON_HAS_FILESYSTEM 1
2428 #elif defined(__cpp_lib_experimental_filesystem)
2429 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2430 #elif !defined(__has_include)
2431 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2432 #elif __has_include(<filesystem>)
2433 #define JSON_HAS_FILESYSTEM 1
2434 #elif __has_include(<experimental/filesystem>)
2435 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2436 #endif
2437
2438 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2439 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2440 #undef JSON_HAS_FILESYSTEM
2441 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2442 #endif
2443
2444 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2445 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2446 #undef JSON_HAS_FILESYSTEM
2447 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2448 #endif
2449
2450 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2451 #if defined(__clang_major__) && __clang_major__ < 7
2452 #undef JSON_HAS_FILESYSTEM
2453 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2454 #endif
2455
2456 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2457 #if defined(_MSC_VER) && _MSC_VER < 1914
2458 #undef JSON_HAS_FILESYSTEM
2459 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2460 #endif
2461
2462 // no filesystem support before iOS 13
2463 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2464 #undef JSON_HAS_FILESYSTEM
2465 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2466 #endif
2467
2468 // no filesystem support before macOS Catalina
2469 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2470 #undef JSON_HAS_FILESYSTEM
2471 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2472 #endif
2473 #endif
2474#endif
2475
2476#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2477 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2478#endif
2479
2480#ifndef JSON_HAS_FILESYSTEM
2481 #define JSON_HAS_FILESYSTEM 0
2482#endif
2483
2484#ifndef JSON_HAS_THREE_WAY_COMPARISON
2485 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2486 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2487 #define JSON_HAS_THREE_WAY_COMPARISON 1
2488 #else
2489 #define JSON_HAS_THREE_WAY_COMPARISON 0
2490 #endif
2491#endif
2492
2493#ifndef JSON_HAS_RANGES
2494 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has a syntax error
2495 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2496 #define JSON_HAS_RANGES 0
2497 #elif defined(__cpp_lib_ranges)
2498 #define JSON_HAS_RANGES 1
2499 #else
2500 #define JSON_HAS_RANGES 0
2501 #endif
2502#endif
2503
2504#ifndef JSON_HAS_STATIC_RTTI
2505 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2506 #define JSON_HAS_STATIC_RTTI 1
2507 #else
2508 #define JSON_HAS_STATIC_RTTI 0
2509 #endif
2510#endif
2511
2512#ifdef JSON_HAS_CPP_17
2513 #define JSON_INLINE_VARIABLE inline
2514#else
2515 #define JSON_INLINE_VARIABLE
2516#endif
2517
2518#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2519 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2520#else
2521 #define JSON_NO_UNIQUE_ADDRESS
2522#endif
2523
2524// disable documentation warnings on clang
2525#if defined(__clang__)
2526 #pragma clang diagnostic push
2527 #pragma clang diagnostic ignored "-Wdocumentation"
2528 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2529#endif
2530
2531// allow disabling exceptions
2532#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2533 #define JSON_THROW(exception) throw exception
2534 #define JSON_TRY try
2535 #define JSON_CATCH(exception) catch(exception)
2536 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2537#else
2538 #include <cstdlib>
2539 #define JSON_THROW(exception) std::abort()
2540 #define JSON_TRY if(true)
2541 #define JSON_CATCH(exception) if(false)
2542 #define JSON_INTERNAL_CATCH(exception) if(false)
2543#endif
2544
2545// override exception macros
2546#if defined(JSON_THROW_USER)
2547 #undef JSON_THROW
2548 #define JSON_THROW JSON_THROW_USER
2549#endif
2550#if defined(JSON_TRY_USER)
2551 #undef JSON_TRY
2552 #define JSON_TRY JSON_TRY_USER
2553#endif
2554#if defined(JSON_CATCH_USER)
2555 #undef JSON_CATCH
2556 #define JSON_CATCH JSON_CATCH_USER
2557 #undef JSON_INTERNAL_CATCH
2558 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2559#endif
2560#if defined(JSON_INTERNAL_CATCH_USER)
2561 #undef JSON_INTERNAL_CATCH
2562 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2563#endif
2564
2565// allow overriding assert
2566#if !defined(JSON_ASSERT)
2567 #include <cassert> // assert
2568 #define JSON_ASSERT(x) assert(x)
2569#endif
2570
2571// allow accessing some private functions (needed by the test suite)
2572#if defined(JSON_TESTS_PRIVATE)
2573 #define JSON_PRIVATE_UNLESS_TESTED public
2574#else
2575 #define JSON_PRIVATE_UNLESS_TESTED private
2576#endif
2577
2583#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2584 template<typename BasicJsonType> \
2585 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2586 { \
2587 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2588 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2589 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2590 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2591 auto it = std::find_if(std::begin(m), std::end(m), \
2592 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2593 { \
2594 return ej_pair.first == e; \
2595 }); \
2596 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2597 } \
2598 template<typename BasicJsonType> \
2599 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2600 { \
2601 /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */ \
2602 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2603 /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */ \
2604 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2605 auto it = std::find_if(std::begin(m), std::end(m), \
2606 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2607 { \
2608 return ej_pair.second == j; \
2609 }); \
2610 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2611 }
2612
2613// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2614// may be removed in the future once the class is split.
2615
2616#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2617 template<template<typename, typename, typename...> class ObjectType, \
2618 template<typename, typename...> class ArrayType, \
2619 class StringType, class BooleanType, class NumberIntegerType, \
2620 class NumberUnsignedType, class NumberFloatType, \
2621 template<typename> class AllocatorType, \
2622 template<typename, typename = void> class JSONSerializer, \
2623 class BinaryType, \
2624 class CustomBaseClass>
2625
2626#define NLOHMANN_BASIC_JSON_TPL \
2627 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2628 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2629 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2630
2631// Macros to simplify conversion from/to types
2632
2633#define NLOHMANN_JSON_EXPAND( x ) x
2634#define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
2635#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2636 NLOHMANN_JSON_PASTE64, \
2637 NLOHMANN_JSON_PASTE63, \
2638 NLOHMANN_JSON_PASTE62, \
2639 NLOHMANN_JSON_PASTE61, \
2640 NLOHMANN_JSON_PASTE60, \
2641 NLOHMANN_JSON_PASTE59, \
2642 NLOHMANN_JSON_PASTE58, \
2643 NLOHMANN_JSON_PASTE57, \
2644 NLOHMANN_JSON_PASTE56, \
2645 NLOHMANN_JSON_PASTE55, \
2646 NLOHMANN_JSON_PASTE54, \
2647 NLOHMANN_JSON_PASTE53, \
2648 NLOHMANN_JSON_PASTE52, \
2649 NLOHMANN_JSON_PASTE51, \
2650 NLOHMANN_JSON_PASTE50, \
2651 NLOHMANN_JSON_PASTE49, \
2652 NLOHMANN_JSON_PASTE48, \
2653 NLOHMANN_JSON_PASTE47, \
2654 NLOHMANN_JSON_PASTE46, \
2655 NLOHMANN_JSON_PASTE45, \
2656 NLOHMANN_JSON_PASTE44, \
2657 NLOHMANN_JSON_PASTE43, \
2658 NLOHMANN_JSON_PASTE42, \
2659 NLOHMANN_JSON_PASTE41, \
2660 NLOHMANN_JSON_PASTE40, \
2661 NLOHMANN_JSON_PASTE39, \
2662 NLOHMANN_JSON_PASTE38, \
2663 NLOHMANN_JSON_PASTE37, \
2664 NLOHMANN_JSON_PASTE36, \
2665 NLOHMANN_JSON_PASTE35, \
2666 NLOHMANN_JSON_PASTE34, \
2667 NLOHMANN_JSON_PASTE33, \
2668 NLOHMANN_JSON_PASTE32, \
2669 NLOHMANN_JSON_PASTE31, \
2670 NLOHMANN_JSON_PASTE30, \
2671 NLOHMANN_JSON_PASTE29, \
2672 NLOHMANN_JSON_PASTE28, \
2673 NLOHMANN_JSON_PASTE27, \
2674 NLOHMANN_JSON_PASTE26, \
2675 NLOHMANN_JSON_PASTE25, \
2676 NLOHMANN_JSON_PASTE24, \
2677 NLOHMANN_JSON_PASTE23, \
2678 NLOHMANN_JSON_PASTE22, \
2679 NLOHMANN_JSON_PASTE21, \
2680 NLOHMANN_JSON_PASTE20, \
2681 NLOHMANN_JSON_PASTE19, \
2682 NLOHMANN_JSON_PASTE18, \
2683 NLOHMANN_JSON_PASTE17, \
2684 NLOHMANN_JSON_PASTE16, \
2685 NLOHMANN_JSON_PASTE15, \
2686 NLOHMANN_JSON_PASTE14, \
2687 NLOHMANN_JSON_PASTE13, \
2688 NLOHMANN_JSON_PASTE12, \
2689 NLOHMANN_JSON_PASTE11, \
2690 NLOHMANN_JSON_PASTE10, \
2691 NLOHMANN_JSON_PASTE9, \
2692 NLOHMANN_JSON_PASTE8, \
2693 NLOHMANN_JSON_PASTE7, \
2694 NLOHMANN_JSON_PASTE6, \
2695 NLOHMANN_JSON_PASTE5, \
2696 NLOHMANN_JSON_PASTE4, \
2697 NLOHMANN_JSON_PASTE3, \
2698 NLOHMANN_JSON_PASTE2, \
2699 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2700#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2701#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2702#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2703#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2704#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2705#define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
2706#define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
2707#define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
2708#define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
2709#define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
2710#define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
2711#define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
2712#define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
2713#define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
2714#define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
2715#define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
2716#define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
2717#define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
2718#define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
2719#define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
2720#define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
2721#define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
2722#define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
2723#define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
2724#define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
2725#define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
2726#define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
2727#define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
2728#define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
2729#define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
2730#define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
2731#define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
2732#define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
2733#define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
2734#define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
2735#define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
2736#define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
2737#define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
2738#define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
2739#define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
2740#define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
2741#define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
2742#define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
2743#define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
2744#define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
2745#define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
2746#define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
2747#define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
2748#define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
2749#define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
2750#define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
2751#define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
2752#define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
2753#define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
2754#define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
2755#define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
2756#define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
2757#define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
2758#define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
2759#define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
2760#define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
2761#define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
2762#define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
2763
2764#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2765#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2766#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1;
2767
2774#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2775 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2776 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2777 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2778 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2779
2786#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2787 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2788 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2789 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2790 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2791
2798#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2799 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2800 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2801
2808#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2809 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2810 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2811 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2812 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2813
2820#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2821 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2822 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2823 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2824 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2825
2832#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2833 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2834 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2835
2842#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...) \
2843 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2844 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2845 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2846 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2847
2854#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2855 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2856 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2857 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2858 friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2859
2866#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2867 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2868 friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2869
2876#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...) \
2877 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2878 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2879 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2880 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
2881
2888#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...) \
2889 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2890 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
2891 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2892 void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
2893
2900#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...) \
2901 template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
2902 void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
2903
2904// inspired from https://stackoverflow.com/a/26745591
2905// allows calling any std function as if (e.g., with begin):
2906// using std::begin; begin(x);
2907//
2908// it allows using the detected idiom to retrieve the return type
2909// of such an expression
2910#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2911 namespace detail { \
2912 using std::std_name; \
2913 \
2914 template<typename... T> \
2915 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2916 } \
2917 \
2918 namespace detail2 { \
2919 struct std_name##_tag \
2920 { \
2921 }; \
2922 \
2923 template<typename... T> \
2924 std_name##_tag std_name(T&&...); \
2925 \
2926 template<typename... T> \
2927 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2928 \
2929 template<typename... T> \
2930 struct would_call_std_##std_name \
2931 { \
2932 static constexpr auto const value = ::nlohmann::detail:: \
2933 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2934 }; \
2935 } /* namespace detail2 */ \
2936 \
2937 template<typename... T> \
2938 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2939 { \
2940 }
2941
2942#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2943 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2944#endif
2945
2946#if JSON_USE_IMPLICIT_CONVERSIONS
2947 #define JSON_EXPLICIT
2948#else
2949 #define JSON_EXPLICIT explicit
2950#endif
2951
2952#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2953 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2954#endif
2955
2956#ifndef JSON_USE_GLOBAL_UDLS
2957 #define JSON_USE_GLOBAL_UDLS 1
2958#endif
2959
2960#if JSON_HAS_THREE_WAY_COMPARISON
2961 #include <compare> // partial_ordering
2962#endif
2963
2965namespace detail
2966{
2967
2969// JSON type enumeration //
2971
3009
3023#if JSON_HAS_THREE_WAY_COMPARISON
3024 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
3025#else
3026 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3027#endif
3028{
3029 static constexpr std::array<std::uint8_t, 9> order = {{
3030 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
3031 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
3032 6 /* binary */
3033 }
3034 };
3035
3036 const auto l_index = static_cast<std::size_t>(lhs);
3037 const auto r_index = static_cast<std::size_t>(rhs);
3038#if JSON_HAS_THREE_WAY_COMPARISON
3039 if (l_index < order.size() && r_index < order.size())
3040 {
3041 return order[l_index] <=> order[r_index]; // *NOPAD*
3042 }
3043 return std::partial_ordering::unordered;
3044#else
3045 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
3046#endif
3047}
3048
3049// GCC selects the built-in operator< over an operator rewritten from
3050// a user-defined spaceship operator
3051// Clang, MSVC, and ICC select the rewritten candidate
3052// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
3053#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
3054inline bool operator<(const value_t lhs, const value_t rhs) noexcept
3055{
3056 return std::is_lt(lhs <=> rhs); // *NOPAD*
3057}
3058#endif
3059
3060} // namespace detail
3062
3063// #include <nlohmann/detail/string_escape.hpp>
3064// __ _____ _____ _____
3065// __| | __| | | | JSON for Modern C++
3066// | | |__ | | | | | | version 3.12.0
3067// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3068//
3069// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3070// SPDX-License-Identifier: MIT
3071
3072
3073
3074// #include <nlohmann/detail/abi_macros.hpp>
3075
3076
3078namespace detail
3079{
3080
3094template<typename StringType>
3095inline void replace_substring(StringType& s, const StringType& f,
3096 const StringType& t)
3097{
3098 JSON_ASSERT(!f.empty());
3099 for (auto pos = s.find(f); // find the first occurrence of f
3100 pos != StringType::npos; // make sure f was found
3101 s.replace(pos, f.size(), t), // replace with t, and
3102 pos = s.find(f, pos + t.size())) // find the next occurrence of f
3103 {}
3104}
3105
3113template<typename StringType>
3114inline StringType escape(StringType s)
3115{
3116 replace_substring(s, StringType{"~"}, StringType{"~0"});
3117 replace_substring(s, StringType{"/"}, StringType{"~1"});
3118 return s;
3119}
3120
3128template<typename StringType>
3129inline void unescape(StringType& s)
3130{
3131 replace_substring(s, StringType{"~1"}, StringType{"/"});
3132 replace_substring(s, StringType{"~0"}, StringType{"~"});
3133}
3134
3135} // namespace detail
3137
3138// #include <nlohmann/detail/input/position_t.hpp>
3139// __ _____ _____ _____
3140// __| | __| | | | JSON for Modern C++
3141// | | |__ | | | | | | version 3.12.0
3142// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3143//
3144// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3145// SPDX-License-Identifier: MIT
3146
3147
3148
3149#include <cstddef> // size_t
3150
3151// #include <nlohmann/detail/abi_macros.hpp>
3152
3153
3155namespace detail
3156{
3157
3160{
3162 std::size_t chars_read_total = 0;
3166 std::size_t lines_read = 0;
3167
3169 constexpr operator size_t() const
3170 {
3171 return chars_read_total;
3172 }
3173};
3174
3175} // namespace detail
3177
3178// #include <nlohmann/detail/macro_scope.hpp>
3179
3180// #include <nlohmann/detail/meta/cpp_future.hpp>
3181// __ _____ _____ _____
3182// __| | __| | | | JSON for Modern C++
3183// | | |__ | | | | | | version 3.12.0
3184// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3185//
3186// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3187// SPDX-FileCopyrightText: 2018 The Abseil Authors
3188// SPDX-License-Identifier: MIT
3189
3190
3191
3192#include <array> // array
3193#include <cstddef> // size_t
3194#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3195#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3196
3197// #include <nlohmann/detail/macro_scope.hpp>
3198
3199
3201namespace detail
3202{
3203
3204template<typename T>
3205using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3206
3207#ifdef JSON_HAS_CPP_14
3208
3209// the following utilities are natively available in C++14
3210using std::enable_if_t;
3211using std::index_sequence;
3212using std::make_index_sequence;
3213using std::index_sequence_for;
3214
3215#else
3216
3217// alias templates to reduce boilerplate
3218template<bool B, typename T = void>
3219using enable_if_t = typename std::enable_if<B, T>::type;
3220
3221// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3222// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3223
3225
3226// integer_sequence
3227//
3228// Class template representing a compile-time integer sequence. An instantiation
3229// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3230// type through its template arguments (which is a common need when
3231// working with C++11 variadic templates). `absl::integer_sequence` is designed
3232// to be a drop-in replacement for C++14's `std::integer_sequence`.
3233//
3234// Example:
3235//
3236// template< class T, T... Ints >
3237// void user_function(integer_sequence<T, Ints...>);
3238//
3239// int main()
3240// {
3241// // user_function's `T` will be deduced to `int` and `Ints...`
3242// // will be deduced to `0, 1, 2, 3, 4`.
3243// user_function(make_integer_sequence<int, 5>());
3244// }
3245template <typename T, T... Ints>
3247{
3248 using value_type = T;
3249 static constexpr std::size_t size() noexcept
3250 {
3251 return sizeof...(Ints);
3252 }
3253};
3254
3255// index_sequence
3256//
3257// A helper template for an `integer_sequence` of `size_t`,
3258// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3259// `std::index_sequence`.
3260template <size_t... Ints>
3261using index_sequence = integer_sequence<size_t, Ints...>;
3262
3264{
3265
3266template <typename Seq, size_t SeqSize, size_t Rem>
3267struct Extend;
3268
3269// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3270template <typename T, T... Ints, size_t SeqSize>
3271struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3272{
3273 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3274};
3275
3276template <typename T, T... Ints, size_t SeqSize>
3277struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3278{
3279 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3280};
3281
3282// Recursion helper for 'make_integer_sequence<T, N>'.
3283// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3284template <typename T, size_t N>
3285struct Gen
3286{
3287 using type =
3288 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3289};
3290
3291template <typename T>
3292struct Gen<T, 0>
3293{
3295};
3296
3297} // namespace utility_internal
3298
3299// Compile-time sequences of integers
3300
3301// make_integer_sequence
3302//
3303// This template alias is equivalent to
3304// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3305// replacement for C++14's `std::make_integer_sequence`.
3306template <typename T, T N>
3308
3309// make_index_sequence
3310//
3311// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3312// and is designed to be a drop-in replacement for C++14's
3313// `std::make_index_sequence`.
3314template <size_t N>
3316
3317// index_sequence_for
3318//
3319// Converts a typename pack into an index sequence of the same length, and
3320// is designed to be a drop-in replacement for C++14's
3321// `std::index_sequence_for()`
3322template <typename... Ts>
3324
3326
3327#endif
3328
3329// dispatch utility (taken from ranges-v3)
3330template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3331template<> struct priority_tag<0> {};
3332
3333// taken from ranges-v3
3334template<typename T>
3336{
3337 static JSON_INLINE_VARIABLE constexpr T value{};
3338};
3339
3340#ifndef JSON_HAS_CPP_17
3341 template<typename T>
3343#endif
3344
3345template<typename T, typename... Args>
3346constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3347{
3348 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3349}
3350
3351} // namespace detail
3353
3354// #include <nlohmann/detail/meta/type_traits.hpp>
3355// __ _____ _____ _____
3356// __| | __| | | | JSON for Modern C++
3357// | | |__ | | | | | | version 3.12.0
3358// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3359//
3360// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3361// SPDX-License-Identifier: MIT
3362
3363
3364
3365#include <limits> // numeric_limits
3366#include <string> // char_traits
3367#include <tuple> // tuple
3368#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3369#include <utility> // declval
3370#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3371 #include <cstddef> // byte
3372#endif
3373// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3374// __ _____ _____ _____
3375// __| | __| | | | JSON for Modern C++
3376// | | |__ | | | | | | version 3.12.0
3377// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3378//
3379// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3380// SPDX-License-Identifier: MIT
3381
3382
3383
3384#include <iterator> // random_access_iterator_tag
3385
3386// #include <nlohmann/detail/abi_macros.hpp>
3387
3388// #include <nlohmann/detail/meta/void_t.hpp>
3389
3390// #include <nlohmann/detail/meta/cpp_future.hpp>
3391
3392
3394namespace detail
3395{
3396
3397template<typename It, typename = void>
3399
3400template<typename It>
3402 It,
3403 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3404 typename It::reference, typename It::iterator_category >>
3405{
3406 using difference_type = typename It::difference_type;
3407 using value_type = typename It::value_type;
3408 using pointer = typename It::pointer;
3409 using reference = typename It::reference;
3410 using iterator_category = typename It::iterator_category;
3411};
3412
3413// This is required as some compilers implement std::iterator_traits in a way that
3414// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3415template<typename T, typename = void>
3417{
3418};
3419
3420template<typename T>
3421struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3422 : iterator_types<T>
3423{
3424};
3425
3426template<typename T>
3428{
3429 using iterator_category = std::random_access_iterator_tag;
3430 using value_type = T;
3431 using difference_type = ptrdiff_t;
3432 using pointer = T*;
3433 using reference = T&;
3434};
3435
3436} // namespace detail
3438
3439// #include <nlohmann/detail/macro_scope.hpp>
3440
3441// #include <nlohmann/detail/meta/call_std/begin.hpp>
3442// __ _____ _____ _____
3443// __| | __| | | | JSON for Modern C++
3444// | | |__ | | | | | | version 3.12.0
3445// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3446//
3447// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3448// SPDX-License-Identifier: MIT
3449
3450
3451
3452// #include <nlohmann/detail/macro_scope.hpp>
3453
3454
3456
3458
3460
3461// #include <nlohmann/detail/meta/call_std/end.hpp>
3462// __ _____ _____ _____
3463// __| | __| | | | JSON for Modern C++
3464// | | |__ | | | | | | version 3.12.0
3465// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3466//
3467// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3468// SPDX-License-Identifier: MIT
3469
3470
3471
3472// #include <nlohmann/detail/macro_scope.hpp>
3473
3474
3476
3478
3480
3481// #include <nlohmann/detail/meta/cpp_future.hpp>
3482
3483// #include <nlohmann/detail/meta/detected.hpp>
3484
3485// #include <nlohmann/json_fwd.hpp>
3486// __ _____ _____ _____
3487// __| | __| | | | JSON for Modern C++
3488// | | |__ | | | | | | version 3.12.0
3489// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3490//
3491// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
3492// SPDX-License-Identifier: MIT
3493
3494#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3495 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3496
3497 #include <cstdint> // int64_t, uint64_t
3498 #include <map> // map
3499 #include <memory> // allocator
3500 #include <string> // string
3501 #include <vector> // vector
3502
3503 // #include <nlohmann/detail/abi_macros.hpp>
3504
3505
3512
3520 template<typename T = void, typename SFINAE = void>
3521 struct adl_serializer;
3522
3525 template<template<typename U, typename V, typename... Args> class ObjectType =
3526 std::map,
3527 template<typename U, typename... Args> class ArrayType = std::vector,
3528 class StringType = std::string, class BooleanType = bool,
3529 class NumberIntegerType = std::int64_t,
3530 class NumberUnsignedType = std::uint64_t,
3531 class NumberFloatType = double,
3532 template<typename U> class AllocatorType = std::allocator,
3533 template<typename T, typename SFINAE = void> class JSONSerializer =
3535 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3536 class CustomBaseClass = void>
3537 class basic_json;
3538
3541 template<typename RefStringType>
3542 class json_pointer;
3543
3549
3552 template<class Key, class T, class IgnoredLess, class Allocator>
3553 struct ordered_map;
3554
3558
3560
3561#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3562
3563
3573namespace detail
3574{
3575
3577// helpers //
3579
3580// Note to maintainers:
3581//
3582// Every trait in this file expects a non-CV-qualified type.
3583// The only exceptions are in the 'aliases for detected' section
3584// (i.e., those of the form: decltype(T::member_function(std::declval<T>())))
3585//
3586// In this case, T has to be properly CV-qualified to constraint the function arguments
3587// (e.g., to_json(BasicJsonType&, const T&))
3588
3589template<typename> struct is_basic_json : std::false_type {};
3590
3592struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3593
3594// used by exceptions create() member functions
3595// true_type for the pointer to possibly cv-qualified basic_json or std::nullptr_t
3596// false_type otherwise
3597template<typename BasicJsonContext>
3599 std::integral_constant < bool,
3600 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3601 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3602{};
3603
3605// json_ref helpers //
3607
3608template<typename>
3609class json_ref;
3610
3611template<typename>
3612struct is_json_ref : std::false_type {};
3613
3614template<typename T>
3615struct is_json_ref<json_ref<T>> : std::true_type {};
3616
3618// aliases for detected //
3620
3621template<typename T>
3622using mapped_type_t = typename T::mapped_type;
3623
3624template<typename T>
3625using key_type_t = typename T::key_type;
3626
3627template<typename T>
3628using value_type_t = typename T::value_type;
3629
3630template<typename T>
3631using difference_type_t = typename T::difference_type;
3632
3633template<typename T>
3634using pointer_t = typename T::pointer;
3635
3636template<typename T>
3637using reference_t = typename T::reference;
3638
3639template<typename T>
3640using iterator_category_t = typename T::iterator_category;
3641
3642template<typename T, typename... Args>
3643using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3644
3645template<typename T, typename... Args>
3646using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3647
3648template<typename T, typename U>
3649using get_template_function = decltype(std::declval<T>().template get<U>());
3650
3651// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3652template<typename BasicJsonType, typename T, typename = void>
3653struct has_from_json : std::false_type {};
3654
3655// trait checking if j.get<T> is valid
3656// use this trait instead of std::is_constructible or std::is_convertible,
3657// both rely on, or make use of implicit conversions, and thus fail when T
3658// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3659template <typename BasicJsonType, typename T>
3664
3665template<typename BasicJsonType, typename T>
3666struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3667{
3668 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3669
3670 static constexpr bool value =
3672 const BasicJsonType&, T&>::value;
3673};
3674
3675// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3676// this overload is used for non-default-constructible user-defined-types
3677template<typename BasicJsonType, typename T, typename = void>
3678struct has_non_default_from_json : std::false_type {};
3679
3680template<typename BasicJsonType, typename T>
3681struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3682{
3683 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3684
3685 static constexpr bool value =
3687 const BasicJsonType&>::value;
3688};
3689
3690// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3691// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3692template<typename BasicJsonType, typename T, typename = void>
3693struct has_to_json : std::false_type {};
3694
3695template<typename BasicJsonType, typename T>
3696struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3697{
3698 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3699
3700 static constexpr bool value =
3701 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3702 T>::value;
3703};
3704
3705template<typename T>
3706using detect_key_compare = typename T::key_compare;
3707
3708template<typename T>
3709struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3710
3711// obtains the actual object key comparator
3712template<typename BasicJsonType>
3714{
3715 using object_t = typename BasicJsonType::object_t;
3716 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3717 using type = typename std::conditional < has_key_compare<object_t>::value,
3718 typename object_t::key_compare, object_comparator_t>::type;
3719};
3720
3721template<typename BasicJsonType>
3723
3725// char_traits //
3727
3728// Primary template of char_traits calls std char_traits
3729template<typename T>
3730struct char_traits : std::char_traits<T>
3731{};
3732
3733// Explicitly define char traits for unsigned char since it is not standard
3734template<>
3735struct char_traits<unsigned char> : std::char_traits<char>
3736{
3737 using char_type = unsigned char;
3738 using int_type = uint64_t;
3739
3740 // Redefine to_int_type function
3741 static int_type to_int_type(char_type c) noexcept
3742 {
3743 return static_cast<int_type>(c);
3744 }
3745
3747 {
3748 return static_cast<char_type>(i);
3749 }
3750
3751 static constexpr int_type eof() noexcept
3752 {
3753 return static_cast<int_type>(std::char_traits<char>::eof());
3754 }
3755};
3756
3757// Explicitly define char traits for signed char since it is not standard
3758template<>
3759struct char_traits<signed char> : std::char_traits<char>
3760{
3761 using char_type = signed char;
3762 using int_type = uint64_t;
3763
3764 // Redefine to_int_type function
3765 static int_type to_int_type(char_type c) noexcept
3766 {
3767 return static_cast<int_type>(c);
3768 }
3769
3771 {
3772 return static_cast<char_type>(i);
3773 }
3774
3775 static constexpr int_type eof() noexcept
3776 {
3777 return static_cast<int_type>(std::char_traits<char>::eof());
3778 }
3779};
3780
3781#if defined(__cpp_lib_byte) && __cpp_lib_byte >= 201603L
3782template<>
3783struct char_traits<std::byte> : std::char_traits<char>
3784{
3785 using char_type = std::byte;
3786 using int_type = uint64_t;
3787
3788 static int_type to_int_type(char_type c) noexcept
3789 {
3790 return static_cast<int_type>(std::to_integer<unsigned char>(c));
3791 }
3792
3793 static char_type to_char_type(int_type i) noexcept
3794 {
3795 return std::byte(static_cast<unsigned char>(i));
3796 }
3797
3798 static constexpr int_type eof() noexcept
3799 {
3800 return static_cast<int_type>(std::char_traits<char>::eof());
3801 }
3802};
3803#endif
3804
3806// is_ functions //
3808
3809// https://en.cppreference.com/w/cpp/types/conjunction
3810template<class...> struct conjunction : std::true_type { };
3811template<class B> struct conjunction<B> : B { };
3812template<class B, class... Bn>
3813struct conjunction<B, Bn...>
3814: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3815
3816// https://en.cppreference.com/w/cpp/types/negation
3817template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3818
3819// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3820// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3821// This causes compile errors in e.g., Clang 3.5 or GCC 4.9.
3822template <typename T>
3823struct is_default_constructible : std::is_default_constructible<T> {};
3824
3825template <typename T1, typename T2>
3826struct is_default_constructible<std::pair<T1, T2>>
3827 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3828
3829template <typename T1, typename T2>
3830struct is_default_constructible<const std::pair<T1, T2>>
3831 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3832
3833template <typename... Ts>
3834struct is_default_constructible<std::tuple<Ts...>>
3835 : conjunction<is_default_constructible<Ts>...> {};
3836
3837template <typename... Ts>
3838struct is_default_constructible<const std::tuple<Ts...>>
3839 : conjunction<is_default_constructible<Ts>...> {};
3840
3841template <typename T, typename... Args>
3842struct is_constructible : std::is_constructible<T, Args...> {};
3843
3844template <typename T1, typename T2>
3845struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3846
3847template <typename T1, typename T2>
3848struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3849
3850template <typename... Ts>
3851struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3852
3853template <typename... Ts>
3854struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3855
3856template<typename T, typename = void>
3857struct is_iterator_traits : std::false_type {};
3858
3859template<typename T>
3873
3874template<typename T>
3876{
3877 private:
3878 using t_ref = typename std::add_lvalue_reference<T>::type;
3879
3880 using iterator = detected_t<result_of_begin, t_ref>;
3881 using sentinel = detected_t<result_of_end, t_ref>;
3882
3883 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3884 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3885 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3886 static constexpr auto is_iterator_begin =
3888
3889 public:
3890 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3891};
3892
3893template<typename R>
3894using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3895
3896template<typename T>
3898
3899// The following implementation of is_complete_type is taken from
3900// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3901// and is written by Xiang Fan who agreed to use it in this library.
3902
3903template<typename T, typename = void>
3904struct is_complete_type : std::false_type {};
3905
3906template<typename T>
3907struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3908
3909template<typename BasicJsonType, typename CompatibleObjectType,
3910 typename = void>
3911struct is_compatible_object_type_impl : std::false_type {};
3912
3913template<typename BasicJsonType, typename CompatibleObjectType>
3915 BasicJsonType, CompatibleObjectType,
3916 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3917 is_detected<key_type_t, CompatibleObjectType>::value >>
3918{
3919 using object_t = typename BasicJsonType::object_t;
3920
3921 // macOS's is_constructible does not play well with nonesuch...
3922 static constexpr bool value =
3923 is_constructible<typename object_t::key_type,
3924 typename CompatibleObjectType::key_type>::value &&
3925 is_constructible<typename object_t::mapped_type,
3926 typename CompatibleObjectType::mapped_type>::value;
3927};
3928
3929template<typename BasicJsonType, typename CompatibleObjectType>
3931 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3932
3933template<typename BasicJsonType, typename ConstructibleObjectType,
3934 typename = void>
3935struct is_constructible_object_type_impl : std::false_type {};
3936
3937template<typename BasicJsonType, typename ConstructibleObjectType>
3939 BasicJsonType, ConstructibleObjectType,
3940 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3941 is_detected<key_type_t, ConstructibleObjectType>::value >>
3942{
3943 using object_t = typename BasicJsonType::object_t;
3944
3945 static constexpr bool value =
3947 (std::is_move_assignable<ConstructibleObjectType>::value ||
3948 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3949 (is_constructible<typename ConstructibleObjectType::key_type,
3950 typename object_t::key_type>::value &&
3951 std::is_same <
3952 typename object_t::mapped_type,
3953 typename ConstructibleObjectType::mapped_type >::value)) ||
3954 (has_from_json<BasicJsonType,
3955 typename ConstructibleObjectType::mapped_type>::value ||
3957 BasicJsonType,
3958 typename ConstructibleObjectType::mapped_type >::value);
3959};
3960
3961template<typename BasicJsonType, typename ConstructibleObjectType>
3963 : is_constructible_object_type_impl<BasicJsonType,
3964 ConstructibleObjectType> {};
3965
3966template<typename BasicJsonType, typename CompatibleStringType>
3972
3973template<typename BasicJsonType, typename ConstructibleStringType>
3975{
3976 // launder type through decltype() to fix compilation failure on ICPC
3977#ifdef __INTEL_COMPILER
3978 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3979#else
3980 using laundered_type = ConstructibleStringType;
3981#endif
3982
3983 static constexpr auto value =
3984 conjunction <
3986 is_detected_exact<typename BasicJsonType::string_t::value_type,
3988};
3989
3990template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3991struct is_compatible_array_type_impl : std::false_type {};
3992
3993template<typename BasicJsonType, typename CompatibleArrayType>
3995 BasicJsonType, CompatibleArrayType,
3996 enable_if_t <
3997 is_detected<iterator_t, CompatibleArrayType>::value&&
3998 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3999// special case for types like std::filesystem::path whose iterator's value_type are themselves
4000// c.f. https://github.com/nlohmann/json/pull/3073
4001 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
4002{
4003 static constexpr bool value =
4004 is_constructible<BasicJsonType,
4006};
4007
4008template<typename BasicJsonType, typename CompatibleArrayType>
4010 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
4011
4012template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
4013struct is_constructible_array_type_impl : std::false_type {};
4014
4015template<typename BasicJsonType, typename ConstructibleArrayType>
4017 BasicJsonType, ConstructibleArrayType,
4018 enable_if_t<std::is_same<ConstructibleArrayType,
4019 typename BasicJsonType::value_type>::value >>
4020 : std::true_type {};
4021
4022template<typename BasicJsonType, typename ConstructibleArrayType>
4024 BasicJsonType, ConstructibleArrayType,
4025 enable_if_t < !std::is_same<ConstructibleArrayType,
4026 typename BasicJsonType::value_type>::value&&
4027 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4028 is_default_constructible<ConstructibleArrayType>::value&&
4029(std::is_move_assignable<ConstructibleArrayType>::value ||
4030 std::is_copy_assignable<ConstructibleArrayType>::value)&&
4031is_detected<iterator_t, ConstructibleArrayType>::value&&
4032is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
4033is_detected<range_value_t, ConstructibleArrayType>::value&&
4034// special case for types like std::filesystem::path whose iterator's value_type are themselves
4035// c.f. https://github.com/nlohmann/json/pull/3073
4036!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
4038detected_t<range_value_t, ConstructibleArrayType >>::value >>
4039{
4041
4042 static constexpr bool value =
4043 std::is_same<value_type,
4044 typename BasicJsonType::array_t::value_type>::value ||
4045 has_from_json<BasicJsonType,
4048 BasicJsonType,
4050};
4051
4052template<typename BasicJsonType, typename ConstructibleArrayType>
4054 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
4055
4056template<typename RealIntegerType, typename CompatibleNumberIntegerType,
4057 typename = void>
4058struct is_compatible_integer_type_impl : std::false_type {};
4059
4060template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4062 RealIntegerType, CompatibleNumberIntegerType,
4063 enable_if_t < std::is_integral<RealIntegerType>::value&&
4064 std::is_integral<CompatibleNumberIntegerType>::value&&
4065 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
4066{
4067 // is there an assert somewhere on overflows?
4068 using RealLimits = std::numeric_limits<RealIntegerType>;
4069 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
4070
4071 static constexpr auto value =
4072 is_constructible<RealIntegerType,
4073 CompatibleNumberIntegerType>::value &&
4074 CompatibleLimits::is_integer &&
4075 RealLimits::is_signed == CompatibleLimits::is_signed;
4076};
4077
4078template<typename RealIntegerType, typename CompatibleNumberIntegerType>
4080 : is_compatible_integer_type_impl<RealIntegerType,
4081 CompatibleNumberIntegerType> {};
4082
4083template<typename BasicJsonType, typename CompatibleType, typename = void>
4084struct is_compatible_type_impl: std::false_type {};
4085
4086template<typename BasicJsonType, typename CompatibleType>
4088 BasicJsonType, CompatibleType,
4089 enable_if_t<is_complete_type<CompatibleType>::value >>
4090{
4091 static constexpr bool value =
4093};
4094
4095template<typename BasicJsonType, typename CompatibleType>
4097 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
4098
4099template<typename T1, typename T2>
4100struct is_constructible_tuple : std::false_type {};
4101
4102template<typename T1, typename... Args>
4103struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
4104
4105template<typename BasicJsonType, typename T>
4106struct is_json_iterator_of : std::false_type {};
4107
4108template<typename BasicJsonType>
4109struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
4110
4111template<typename BasicJsonType>
4112struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
4113{};
4114
4115// checks if a given type T is a template specialization of Primary
4116template<template <typename...> class Primary, typename T>
4117struct is_specialization_of : std::false_type {};
4118
4119template<template <typename...> class Primary, typename... Args>
4120struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
4121
4122template<typename T>
4124
4125// checks if A and B are comparable using Compare functor
4126template<typename Compare, typename A, typename B, typename = void>
4127struct is_comparable : std::false_type {};
4128
4129template<typename Compare, typename A, typename B>
4130struct is_comparable<Compare, A, B, void_t<
4131decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
4132decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
4133>> : std::true_type {};
4134
4135template<typename T>
4136using detect_is_transparent = typename T::is_transparent;
4137
4138// type trait to check if KeyType can be used as an object key (without a BasicJsonType)
4139// see is_usable_as_basic_json_key_type below
4140template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4141 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4142using is_usable_as_key_type = typename std::conditional <
4144 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4145 ObjectKeyType>::value)
4146 && (!RequireTransparentComparator
4147 || is_detected <detect_is_transparent, Comparator>::value)
4149 std::true_type,
4150 std::false_type >::type;
4151
4152// type trait to check if KeyType can be used as an object key
4153// true if:
4154// - KeyType is comparable with BasicJsonType::object_t::key_type
4155// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4156// - the comparator is transparent or RequireTransparentComparator is false
4157// - KeyType is not a JSON iterator or json_pointer
4158template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4159 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4160using is_usable_as_basic_json_key_type = typename std::conditional <
4161 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4162 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4163 RequireTransparentComparator, ExcludeObjectKeyType>::value
4165 std::true_type,
4166 std::false_type >::type;
4167
4168template<typename ObjectType, typename KeyType>
4169using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4170
4171// type trait to check if object_t has an erase() member functions accepting KeyType
4172template<typename BasicJsonType, typename KeyType>
4173using has_erase_with_key_type = typename std::conditional <
4174 is_detected <
4176 typename BasicJsonType::object_t, KeyType >::value,
4177 std::true_type,
4178 std::false_type >::type;
4179
4180// a naive helper to check if a type is an ordered_map (exploits the fact that
4181// ordered_map inherits capacity() from std::vector)
4182template <typename T>
4184{
4185 using one = char;
4186
4187 struct two
4188 {
4189 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4190 };
4191
4192 template <typename C> static one test( decltype(&C::capacity) ) ;
4193 template <typename C> static two test(...);
4194
4195 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4196};
4197
4198// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4199template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4201{
4202 return static_cast<T>(value);
4203}
4204
4205template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4207{
4208 return value;
4209}
4210
4211template<typename... Types>
4213
4214template<typename... Types>
4216
4217template<typename... Types>
4219
4220// there's a disjunction trait in another PR; replace when merged
4221template<typename... Types>
4222using same_sign = std::integral_constant < bool,
4223 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4224
4225template<typename OfType, typename T>
4226using never_out_of_range = std::integral_constant < bool,
4227 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4228 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4229
4230template<typename OfType, typename T,
4231 bool OfTypeSigned = std::is_signed<OfType>::value,
4232 bool TSigned = std::is_signed<T>::value>
4234
4235template<typename OfType, typename T>
4236struct value_in_range_of_impl2<OfType, T, false, false>
4237{
4238 static constexpr bool test(T val)
4239 {
4240 using CommonType = typename std::common_type<OfType, T>::type;
4241 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4242 }
4243};
4244
4245template<typename OfType, typename T>
4246struct value_in_range_of_impl2<OfType, T, true, false>
4247{
4248 static constexpr bool test(T val)
4249 {
4250 using CommonType = typename std::common_type<OfType, T>::type;
4251 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4252 }
4253};
4254
4255template<typename OfType, typename T>
4256struct value_in_range_of_impl2<OfType, T, false, true>
4257{
4258 static constexpr bool test(T val)
4259 {
4260 using CommonType = typename std::common_type<OfType, T>::type;
4261 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4262 }
4263};
4264
4265template<typename OfType, typename T>
4266struct value_in_range_of_impl2<OfType, T, true, true>
4267{
4268 static constexpr bool test(T val)
4269 {
4270 using CommonType = typename std::common_type<OfType, T>::type;
4271 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4272 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4273 }
4274};
4275
4276template<typename OfType, typename T,
4277 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4280
4281template<typename OfType, typename T>
4282struct value_in_range_of_impl1<OfType, T, false>
4283{
4284 static constexpr bool test(T val)
4285 {
4287 }
4288};
4289
4290template<typename OfType, typename T>
4291struct value_in_range_of_impl1<OfType, T, true>
4292{
4293 static constexpr bool test(T /*val*/)
4294 {
4295 return true;
4296 }
4297};
4298
4299template<typename OfType, typename T>
4300constexpr bool value_in_range_of(T val)
4301{
4303}
4304
4305template<bool Value>
4306using bool_constant = std::integral_constant<bool, Value>;
4307
4309// is_c_string
4311
4312namespace impl
4313{
4314
4315template<typename T>
4316constexpr bool is_c_string()
4317{
4318 using TUnExt = typename std::remove_extent<T>::type;
4319 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4320 using TUnPtr = typename std::remove_pointer<T>::type;
4321 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4322 return
4323 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4324 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4325}
4326
4327} // namespace impl
4328
4329// checks whether T is a [cv] char */[cv] char[] C string
4330template<typename T>
4331struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4332
4333template<typename T>
4335
4337// is_transparent
4339
4340namespace impl
4341{
4342
4343template<typename T>
4344constexpr bool is_transparent()
4345{
4347}
4348
4349} // namespace impl
4350
4351// checks whether T has a member named is_transparent
4352template<typename T>
4353struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4354
4356
4357} // namespace detail
4359
4360// #include <nlohmann/detail/string_concat.hpp>
4361// __ _____ _____ _____
4362// __| | __| | | | JSON for Modern C++
4363// | | |__ | | | | | | version 3.12.0
4364// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4365//
4366// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4367// SPDX-License-Identifier: MIT
4368
4369
4370
4371#include <cstring> // strlen
4372#include <string> // string
4373#include <utility> // forward
4374
4375// #include <nlohmann/detail/meta/cpp_future.hpp>
4376
4377// #include <nlohmann/detail/meta/detected.hpp>
4378
4379
4381namespace detail
4382{
4383
4384inline std::size_t concat_length()
4385{
4386 return 0;
4387}
4388
4389template<typename... Args>
4390inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4391
4392template<typename StringType, typename... Args>
4393inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4394
4395template<typename... Args>
4396inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4397{
4398 return 1 + concat_length(rest...);
4399}
4400
4401template<typename... Args>
4402inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4403{
4404 // cppcheck-suppress ignoredReturnValue
4405 return ::strlen(cstr) + concat_length(rest...);
4406}
4407
4408template<typename StringType, typename... Args>
4409inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4410{
4411 return str.size() + concat_length(rest...);
4412}
4413
4414template<typename OutStringType>
4415inline void concat_into(OutStringType& /*out*/)
4416{}
4417
4418template<typename StringType, typename Arg>
4419using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4420
4421template<typename StringType, typename Arg>
4423
4424template<typename StringType, typename Arg>
4425using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4426
4427template<typename StringType, typename Arg>
4429
4430template<typename StringType, typename Arg>
4431using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4432
4433template<typename StringType, typename Arg>
4435
4436template<typename StringType, typename Arg>
4437using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4438
4439template<typename StringType, typename Arg>
4441
4442template < typename OutStringType, typename Arg, typename... Args,
4443 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4445inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4446
4447template < typename OutStringType, typename Arg, typename... Args,
4448 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4451inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4452
4453template < typename OutStringType, typename Arg, typename... Args,
4454 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4458inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4459
4460template<typename OutStringType, typename Arg, typename... Args,
4462inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4463{
4464 out.append(std::forward<Arg>(arg));
4465 concat_into(out, std::forward<Args>(rest)...);
4466}
4467
4468template < typename OutStringType, typename Arg, typename... Args,
4469 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4470 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4471inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4472{
4473 out += std::forward<Arg>(arg);
4474 concat_into(out, std::forward<Args>(rest)...);
4475}
4476
4477template < typename OutStringType, typename Arg, typename... Args,
4478 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4481inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4482{
4483 out.append(arg.begin(), arg.end());
4484 concat_into(out, std::forward<Args>(rest)...);
4485}
4486
4487template < typename OutStringType, typename Arg, typename... Args,
4488 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4489 && !detect_string_can_append_op<OutStringType, Arg>::value
4490 && !detect_string_can_append_iter<OutStringType, Arg>::value
4491 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4492inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4493{
4494 out.append(arg.data(), arg.size());
4495 concat_into(out, std::forward<Args>(rest)...);
4496}
4497
4498template<typename OutStringType = std::string, typename... Args>
4499inline OutStringType concat(Args && ... args)
4500{
4501 OutStringType str;
4502 str.reserve(concat_length(args...));
4503 concat_into(str, std::forward<Args>(args)...);
4504 return str;
4505}
4506
4507} // namespace detail
4509
4510
4511// With -Wweak-vtables, Clang will complain about the exception classes as they
4512// have no out-of-line virtual method definitions and their vtable will be
4513// emitted in every translation unit. This issue cannot be fixed with a
4514// header-only library as there is no implementation file to move these
4515// functions to. As a result, we suppress this warning here to avoid client
4516// code stumbling over this. See https://github.com/nlohmann/json/issues/4087
4517// for a discussion.
4518#if defined(__clang__)
4519 #pragma clang diagnostic push
4520 #pragma clang diagnostic ignored "-Wweak-vtables"
4521#endif
4522
4524namespace detail
4525{
4526
4528// exceptions //
4530
4533class exception : public std::exception
4534{
4535 public:
4537 const char* what() const noexcept override
4538 {
4539 return m.what();
4540 }
4541
4543 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4544
4545 protected:
4547 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4548
4549 static std::string name(const std::string& ename, int id_)
4550 {
4551 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4552 }
4553
4554 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4555 {
4556 return "";
4557 }
4558
4559 template<typename BasicJsonType>
4560 static std::string diagnostics(const BasicJsonType* leaf_element)
4561 {
4562#if JSON_DIAGNOSTICS
4563 std::vector<std::string> tokens;
4564 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4565 {
4566 switch (current->m_parent->type())
4567 {
4568 case value_t::array:
4569 {
4570 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4571 {
4572 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4573 {
4574 tokens.emplace_back(std::to_string(i));
4575 break;
4576 }
4577 }
4578 break;
4579 }
4580
4581 case value_t::object:
4582 {
4583 for (const auto& element : *current->m_parent->m_data.m_value.object)
4584 {
4585 if (&element.second == current)
4586 {
4587 tokens.emplace_back(element.first.c_str());
4588 break;
4589 }
4590 }
4591 break;
4592 }
4593
4594 case value_t::null: // LCOV_EXCL_LINE
4595 case value_t::string: // LCOV_EXCL_LINE
4596 case value_t::boolean: // LCOV_EXCL_LINE
4597 case value_t::number_integer: // LCOV_EXCL_LINE
4598 case value_t::number_unsigned: // LCOV_EXCL_LINE
4599 case value_t::number_float: // LCOV_EXCL_LINE
4600 case value_t::binary: // LCOV_EXCL_LINE
4601 case value_t::discarded: // LCOV_EXCL_LINE
4602 default: // LCOV_EXCL_LINE
4603 break; // LCOV_EXCL_LINE
4604 }
4605 }
4606
4607 if (tokens.empty())
4608 {
4609 return "";
4610 }
4611
4612 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4613 [](const std::string & a, const std::string & b)
4614 {
4615 return concat(a, '/', detail::escape(b));
4616 });
4617
4618 return concat('(', str, ") ", get_byte_positions(leaf_element));
4619#else
4620 return get_byte_positions(leaf_element);
4621#endif
4622 }
4623
4624 private:
4626 std::runtime_error m;
4627#if JSON_DIAGNOSTIC_POSITIONS
4628 template<typename BasicJsonType>
4629 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4630 {
4631 if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
4632 {
4633 return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
4634 }
4635 return "";
4636 }
4637#else
4638 template<typename BasicJsonType>
4639 static std::string get_byte_positions(const BasicJsonType* leaf_element)
4640 {
4641 static_cast<void>(leaf_element);
4642 return "";
4643 }
4644#endif
4645};
4646
4649class parse_error : public exception
4650{
4651 public:
4661 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4662 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4663 {
4664 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4665 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4666 return {id_, pos.chars_read_total, w.c_str()};
4667 }
4668
4669 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4670 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4671 {
4672 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4673 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4674 ": ", exception::diagnostics(context), what_arg);
4675 return {id_, byte_, w.c_str()};
4676 }
4677
4687 const std::size_t byte;
4688
4689 private:
4690 parse_error(int id_, std::size_t byte_, const char* what_arg)
4691 : exception(id_, what_arg), byte(byte_) {}
4692
4693 static std::string position_string(const position_t& pos)
4694 {
4695 return concat(" at line ", std::to_string(pos.lines_read + 1),
4696 ", column ", std::to_string(pos.chars_read_current_line));
4697 }
4698};
4699
4702class invalid_iterator : public exception
4703{
4704 public:
4705 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4706 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4707 {
4708 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4709 return {id_, w.c_str()};
4710 }
4711
4712 private:
4714 invalid_iterator(int id_, const char* what_arg)
4715 : exception(id_, what_arg) {}
4716};
4717
4720class type_error : public exception
4721{
4722 public:
4723 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4724 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4725 {
4726 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4727 return {id_, w.c_str()};
4728 }
4729
4730 private:
4732 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4733};
4734
4737class out_of_range : public exception
4738{
4739 public:
4740 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4741 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4742 {
4743 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4744 return {id_, w.c_str()};
4745 }
4746
4747 private:
4749 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4750};
4751
4754class other_error : public exception
4755{
4756 public:
4757 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4758 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4759 {
4760 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4761 return {id_, w.c_str()};
4762 }
4763
4764 private:
4766 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4767};
4768
4769} // namespace detail
4771
4772#if defined(__clang__)
4773 #pragma clang diagnostic pop
4774#endif
4775
4776// #include <nlohmann/detail/macro_scope.hpp>
4777
4778// #include <nlohmann/detail/meta/cpp_future.hpp>
4779
4780// #include <nlohmann/detail/meta/identity_tag.hpp>
4781// __ _____ _____ _____
4782// __| | __| | | | JSON for Modern C++
4783// | | |__ | | | | | | version 3.12.0
4784// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4785//
4786// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4787// SPDX-License-Identifier: MIT
4788
4789
4790
4791// #include <nlohmann/detail/abi_macros.hpp>
4792
4793
4795namespace detail
4796{
4797
4798// dispatching helper struct
4799template <class T> struct identity_tag {};
4800
4801} // namespace detail
4803
4804// #include <nlohmann/detail/meta/std_fs.hpp>
4805// __ _____ _____ _____
4806// __| | __| | | | JSON for Modern C++
4807// | | |__ | | | | | | version 3.12.0
4808// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4809//
4810// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
4811// SPDX-License-Identifier: MIT
4812
4813
4814
4815// #include <nlohmann/detail/macro_scope.hpp>
4816
4817
4818#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4819#include <experimental/filesystem>
4821namespace detail
4822{
4823namespace std_fs = std::experimental::filesystem;
4824} // namespace detail
4826#elif JSON_HAS_FILESYSTEM
4827#include <filesystem> // NOLINT(build/c++17)
4829namespace detail
4830{
4831namespace std_fs = std::filesystem;
4832} // namespace detail
4834#endif
4835
4836// #include <nlohmann/detail/meta/type_traits.hpp>
4837
4838// #include <nlohmann/detail/string_concat.hpp>
4839
4840// #include <nlohmann/detail/value_t.hpp>
4841
4842
4843// include after macro_scope.hpp
4844#ifdef JSON_HAS_CPP_17
4845 #include <optional> // optional
4846#endif
4847
4848#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
4849 #include <string_view> // u8string_view
4850#endif
4851
4853namespace detail
4854{
4855
4856template<typename BasicJsonType>
4857inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4858{
4859 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4860 {
4861 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4862 }
4863 n = nullptr;
4864}
4865
4866#ifdef JSON_HAS_CPP_17
4867template<typename BasicJsonType, typename T>
4868void from_json(const BasicJsonType& j, std::optional<T>& opt)
4869{
4870 if (j.is_null())
4871 {
4872 opt = std::nullopt;
4873 }
4874 else
4875 {
4876 opt.emplace(j.template get<T>());
4877 }
4878}
4879#endif // JSON_HAS_CPP_17
4880
4881// overloads for basic_json template parameters
4882template < typename BasicJsonType, typename ArithmeticType,
4883 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4884 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4885 int > = 0 >
4886void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4887{
4888 switch (static_cast<value_t>(j))
4889 {
4891 {
4892 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4893 break;
4894 }
4896 {
4897 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4898 break;
4899 }
4901 {
4902 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4903 break;
4904 }
4905
4906 case value_t::null:
4907 case value_t::object:
4908 case value_t::array:
4909 case value_t::string:
4910 case value_t::boolean:
4911 case value_t::binary:
4912 case value_t::discarded:
4913 default:
4914 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4915 }
4916}
4917
4918template<typename BasicJsonType>
4919inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4920{
4921 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4922 {
4923 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4924 }
4925 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4926}
4927
4928template<typename BasicJsonType>
4929inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4930{
4931 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4932 {
4933 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4934 }
4935 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4936}
4937
4938template <
4939 typename BasicJsonType, typename StringType,
4940 enable_if_t <
4941 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4942 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4943 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4944 && !is_json_ref<StringType>::value, int > = 0 >
4945inline void from_json(const BasicJsonType& j, StringType& s)
4946{
4947 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4948 {
4949 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4950 }
4951
4952 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4953}
4954
4955template<typename BasicJsonType>
4956inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4957{
4958 get_arithmetic_value(j, val);
4959}
4960
4961template<typename BasicJsonType>
4962inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4963{
4964 get_arithmetic_value(j, val);
4965}
4966
4967template<typename BasicJsonType>
4968inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4969{
4970 get_arithmetic_value(j, val);
4971}
4972
4973#if !JSON_DISABLE_ENUM_SERIALIZATION
4974template<typename BasicJsonType, typename EnumType,
4975 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4976inline void from_json(const BasicJsonType& j, EnumType& e)
4977{
4978 typename std::underlying_type<EnumType>::type val;
4979 get_arithmetic_value(j, val);
4980 e = static_cast<EnumType>(val);
4981}
4982#endif // JSON_DISABLE_ENUM_SERIALIZATION
4983
4984// forward_list doesn't have an insert method
4985template<typename BasicJsonType, typename T, typename Allocator,
4986 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4987inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4988{
4989 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4990 {
4991 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4992 }
4993 l.clear();
4994 std::transform(j.rbegin(), j.rend(),
4995 std::front_inserter(l), [](const BasicJsonType & i)
4996 {
4997 return i.template get<T>();
4998 });
4999}
5000
5001// valarray doesn't have an insert method
5002template<typename BasicJsonType, typename T,
5003 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
5004inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
5005{
5006 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5007 {
5008 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5009 }
5010 l.resize(j.size());
5011 std::transform(j.begin(), j.end(), std::begin(l),
5012 [](const BasicJsonType & elem)
5013 {
5014 return elem.template get<T>();
5015 });
5016}
5017
5018template<typename BasicJsonType, typename T, std::size_t N>
5019auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5020-> decltype(j.template get<T>(), void())
5021{
5022 for (std::size_t i = 0; i < N; ++i)
5023 {
5024 arr[i] = j.at(i).template get<T>();
5025 }
5026}
5027
5028template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
5029auto from_json(const BasicJsonType& j, T (&arr)[N1][N2]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5030-> decltype(j.template get<T>(), void())
5031{
5032 for (std::size_t i1 = 0; i1 < N1; ++i1)
5033 {
5034 for (std::size_t i2 = 0; i2 < N2; ++i2)
5035 {
5036 arr[i1][i2] = j.at(i1).at(i2).template get<T>();
5037 }
5038 }
5039}
5040
5041template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
5042auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5043-> decltype(j.template get<T>(), void())
5044{
5045 for (std::size_t i1 = 0; i1 < N1; ++i1)
5046 {
5047 for (std::size_t i2 = 0; i2 < N2; ++i2)
5048 {
5049 for (std::size_t i3 = 0; i3 < N3; ++i3)
5050 {
5051 arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
5052 }
5053 }
5054 }
5055}
5056
5057template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
5058auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5059-> decltype(j.template get<T>(), void())
5060{
5061 for (std::size_t i1 = 0; i1 < N1; ++i1)
5062 {
5063 for (std::size_t i2 = 0; i2 < N2; ++i2)
5064 {
5065 for (std::size_t i3 = 0; i3 < N3; ++i3)
5066 {
5067 for (std::size_t i4 = 0; i4 < N4; ++i4)
5068 {
5069 arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
5070 }
5071 }
5072 }
5073 }
5074}
5075
5076template<typename BasicJsonType>
5077inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
5078{
5079 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
5080}
5081
5082template<typename BasicJsonType, typename T, std::size_t N>
5083auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
5084 priority_tag<2> /*unused*/)
5085-> decltype(j.template get<T>(), void())
5086{
5087 for (std::size_t i = 0; i < N; ++i)
5088 {
5089 arr[i] = j.at(i).template get<T>();
5090 }
5091}
5092
5093template<typename BasicJsonType, typename ConstructibleArrayType,
5095 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5096 int> = 0>
5097auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
5098-> decltype(
5099 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
5101 void())
5102{
5103 using std::end;
5104
5105 ConstructibleArrayType ret;
5106 ret.reserve(j.size());
5107 std::transform(j.begin(), j.end(),
5108 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
5109 {
5110 // get<BasicJsonType>() returns *this, this won't call a from_json
5111 // method when value_type is BasicJsonType
5113 });
5114 arr = std::move(ret);
5115}
5116
5117template<typename BasicJsonType, typename ConstructibleArrayType,
5119 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
5120 int> = 0>
5121inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
5122 priority_tag<0> /*unused*/)
5123{
5124 using std::end;
5125
5126 ConstructibleArrayType ret;
5127 std::transform(
5128 j.begin(), j.end(), std::inserter(ret, end(ret)),
5129 [](const BasicJsonType & i)
5130 {
5131 // get<BasicJsonType>() returns *this, this won't call a from_json
5132 // method when value_type is BasicJsonType
5134 });
5135 arr = std::move(ret);
5136}
5137
5138template < typename BasicJsonType, typename ConstructibleArrayType,
5139 enable_if_t <
5140 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
5141 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
5143 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
5144 !is_basic_json<ConstructibleArrayType>::value,
5145 int > = 0 >
5146auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
5147-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
5149void())
5150{
5151 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5152 {
5153 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5154 }
5155
5157}
5158
5159template < typename BasicJsonType, typename T, std::size_t... Idx >
5160std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
5161 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
5162{
5163 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
5164}
5165
5166template < typename BasicJsonType, typename T, std::size_t N >
5167auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
5168-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
5169{
5170 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5171 {
5172 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5173 }
5174
5175 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
5176}
5177
5178template<typename BasicJsonType>
5179inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
5180{
5181 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
5182 {
5183 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
5184 }
5185
5186 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
5187}
5188
5189template<typename BasicJsonType, typename ConstructibleObjectType,
5190 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
5191inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
5192{
5193 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
5194 {
5195 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
5196 }
5197
5198 ConstructibleObjectType ret;
5199 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
5200 using value_type = typename ConstructibleObjectType::value_type;
5201 std::transform(
5202 inner_object->begin(), inner_object->end(),
5203 std::inserter(ret, ret.begin()),
5204 [](typename BasicJsonType::object_t::value_type const & p)
5205 {
5206 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
5207 });
5208 obj = std::move(ret);
5209}
5210
5211// overload for arithmetic types, not chosen for basic_json template arguments
5212// (BooleanType, etc.); note: Is it really necessary to provide explicit
5213// overloads for boolean_t etc. in case of a custom BooleanType which is not
5214// an arithmetic type?
5215template < typename BasicJsonType, typename ArithmeticType,
5216 enable_if_t <
5217 std::is_arithmetic<ArithmeticType>::value&&
5218 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
5219 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
5220 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
5221 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
5222 int > = 0 >
5223inline void from_json(const BasicJsonType& j, ArithmeticType& val)
5224{
5225 switch (static_cast<value_t>(j))
5226 {
5228 {
5229 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
5230 break;
5231 }
5233 {
5234 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
5235 break;
5236 }
5238 {
5239 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
5240 break;
5241 }
5242 case value_t::boolean:
5243 {
5244 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5245 break;
5246 }
5247
5248 case value_t::null:
5249 case value_t::object:
5250 case value_t::array:
5251 case value_t::string:
5252 case value_t::binary:
5253 case value_t::discarded:
5254 default:
5255 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5256 }
5257}
5258
5259template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5260std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5261{
5262 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5263}
5264
5265template<typename BasicJsonType>
5266std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
5267{
5268 return {};
5269}
5270
5271template < typename BasicJsonType, class A1, class A2 >
5272std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5273{
5274 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5275 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5276}
5277
5278template<typename BasicJsonType, typename A1, typename A2>
5279inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5280{
5281 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5282}
5283
5284template<typename BasicJsonType, typename... Args>
5285std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5286{
5287 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5288}
5289
5290template<typename BasicJsonType, typename... Args>
5291inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5292{
5293 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5294}
5295
5296template<typename BasicJsonType, typename TupleRelated>
5297auto from_json(BasicJsonType&& j, TupleRelated&& t)
5298-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5299{
5300 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5301 {
5302 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5303 }
5304
5305 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5306}
5307
5308template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5309 typename = enable_if_t < !std::is_constructible <
5310 typename BasicJsonType::string_t, Key >::value >>
5311inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5312{
5313 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5314 {
5315 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5316 }
5317 m.clear();
5318 for (const auto& p : j)
5319 {
5320 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5321 {
5322 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5323 }
5324 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5325 }
5326}
5327
5328template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5329 typename = enable_if_t < !std::is_constructible <
5330 typename BasicJsonType::string_t, Key >::value >>
5331inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5332{
5333 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5334 {
5335 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5336 }
5337 m.clear();
5338 for (const auto& p : j)
5339 {
5340 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5341 {
5342 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5343 }
5344 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5345 }
5346}
5347
5348#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5349template<typename BasicJsonType>
5350inline void from_json(const BasicJsonType& j, std_fs::path& p)
5351{
5352 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5353 {
5354 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5355 }
5356 const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5357 // Checking for C++20 standard or later can be insufficient in case the
5358 // library support for char8_t is either incomplete or was disabled
5359 // altogether. Use the __cpp_lib_char8_t feature test instead.
5360#if defined(__cpp_lib_char8_t) && (__cpp_lib_char8_t >= 201907L)
5361 p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
5362#else
5363 p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
5364#endif
5365}
5366#endif
5367
5369{
5370 template<typename BasicJsonType, typename T>
5371 auto operator()(const BasicJsonType& j, T&& val) const
5372 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5373 -> decltype(from_json(j, std::forward<T>(val)))
5374 {
5375 return from_json(j, std::forward<T>(val));
5376 }
5377};
5378
5379} // namespace detail
5380
5381#ifndef JSON_HAS_CPP_17
5385namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5386{
5387#endif
5388JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5390#ifndef JSON_HAS_CPP_17
5391} // namespace
5392#endif
5393
5395
5396// #include <nlohmann/detail/conversions/to_json.hpp>
5397// __ _____ _____ _____
5398// __| | __| | | | JSON for Modern C++
5399// | | |__ | | | | | | version 3.12.0
5400// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5401//
5402// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5403// SPDX-License-Identifier: MIT
5404
5405
5406
5407// #include <nlohmann/detail/macro_scope.hpp>
5408// JSON_HAS_CPP_17
5409#ifdef JSON_HAS_CPP_17
5410 #include <optional> // optional
5411#endif
5412
5413#include <algorithm> // copy
5414#include <iterator> // begin, end
5415#include <memory> // allocator_traits
5416#include <string> // basic_string, char_traits
5417#include <tuple> // tuple, get
5418#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5419#include <utility> // move, forward, declval, pair
5420#include <valarray> // valarray
5421#include <vector> // vector
5422
5423// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5424// __ _____ _____ _____
5425// __| | __| | | | JSON for Modern C++
5426// | | |__ | | | | | | version 3.12.0
5427// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5428//
5429// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5430// SPDX-License-Identifier: MIT
5431
5432
5433
5434#include <cstddef> // size_t
5435#include <iterator> // forward_iterator_tag
5436#include <tuple> // tuple_size, get, tuple_element
5437#include <utility> // move
5438
5439#if JSON_HAS_RANGES
5440 #include <ranges> // enable_borrowed_range
5441#endif
5442
5443// #include <nlohmann/detail/abi_macros.hpp>
5444
5445// #include <nlohmann/detail/meta/type_traits.hpp>
5446
5447// #include <nlohmann/detail/string_utils.hpp>
5448// __ _____ _____ _____
5449// __| | __| | | | JSON for Modern C++
5450// | | |__ | | | | | | version 3.12.0
5451// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5452//
5453// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
5454// SPDX-License-Identifier: MIT
5455
5456
5457
5458#include <cstddef> // size_t
5459#include <string> // string, to_string
5460
5461// #include <nlohmann/detail/abi_macros.hpp>
5462
5463
5465namespace detail
5466{
5467
5468template<typename StringType>
5469void int_to_string(StringType& target, std::size_t value)
5470{
5471 // For ADL
5472 using std::to_string;
5473 target = to_string(value);
5474}
5475
5476template<typename StringType>
5477StringType to_string(std::size_t value)
5478{
5479 StringType result;
5480 int_to_string(result, value);
5481 return result;
5482}
5483
5484} // namespace detail
5486
5487// #include <nlohmann/detail/value_t.hpp>
5488
5489
5491namespace detail
5492{
5493
5494template<typename IteratorType> class iteration_proxy_value
5495{
5496 public:
5497 using difference_type = std::ptrdiff_t;
5501 using iterator_category = std::forward_iterator_tag;
5502 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5503
5504 private:
5506 IteratorType anchor{};
5508 std::size_t array_index = 0;
5510 mutable std::size_t array_index_last = 0;
5512 mutable string_type array_index_str = "0";
5514 string_type empty_str{};
5515
5516 public:
5517 explicit iteration_proxy_value() = default;
5518 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5519 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5520 && std::is_nothrow_default_constructible<string_type>::value)
5521 : anchor(std::move(it))
5522 , array_index(array_index_)
5523 {}
5524
5527 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5529 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5530 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5532 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5533 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5535
5537 const iteration_proxy_value& operator*() const
5538 {
5539 return *this;
5540 }
5541
5544 {
5545 ++anchor;
5546 ++array_index;
5547
5548 return *this;
5549 }
5550
5551 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5552 {
5553 auto tmp = iteration_proxy_value(anchor, array_index);
5554 ++anchor;
5555 ++array_index;
5556 return tmp;
5557 }
5558
5561 {
5562 return anchor == o.anchor;
5563 }
5564
5567 {
5568 return anchor != o.anchor;
5569 }
5570
5572 const string_type& key() const
5573 {
5574 JSON_ASSERT(anchor.m_object != nullptr);
5575
5576 switch (anchor.m_object->type())
5577 {
5578 // use integer array index as key
5579 case value_t::array:
5580 {
5581 if (array_index != array_index_last)
5582 {
5583 int_to_string( array_index_str, array_index );
5584 array_index_last = array_index;
5585 }
5586 return array_index_str;
5587 }
5588
5589 // use key from the object
5590 case value_t::object:
5591 return anchor.key();
5592
5593 // use an empty key for all primitive types
5594 case value_t::null:
5595 case value_t::string:
5596 case value_t::boolean:
5600 case value_t::binary:
5601 case value_t::discarded:
5602 default:
5603 return empty_str;
5604 }
5605 }
5606
5608 typename IteratorType::reference value() const
5609 {
5610 return anchor.value();
5611 }
5612};
5613
5615template<typename IteratorType> class iteration_proxy
5616{
5617 private:
5619 typename IteratorType::pointer container = nullptr;
5620
5621 public:
5622 explicit iteration_proxy() = default;
5623
5625 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5626 : container(&cont) {}
5627
5630 iteration_proxy(iteration_proxy&&) noexcept = default;
5631 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5632 ~iteration_proxy() = default;
5633
5635 iteration_proxy_value<IteratorType> begin() const noexcept
5636 {
5637 return iteration_proxy_value<IteratorType>(container->begin());
5638 }
5639
5642 {
5643 return iteration_proxy_value<IteratorType>(container->end());
5644 }
5645};
5646
5647// Structured Bindings Support
5648// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5649// And see https://github.com/nlohmann/json/pull/1391
5650template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5651auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5652{
5653 return i.key();
5654}
5655// Structured Bindings Support
5656// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5657// And see https://github.com/nlohmann/json/pull/1391
5658template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5659auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5660{
5661 return i.value();
5662}
5663
5664} // namespace detail
5666
5667// The Addition to the STD Namespace is required to add
5668// Structured Bindings Support to the iteration_proxy_value class
5669// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5670// And see https://github.com/nlohmann/json/pull/1391
5671namespace std
5672{
5673
5674#if defined(__clang__)
5675 // Fix: https://github.com/nlohmann/json/issues/1401
5676 #pragma clang diagnostic push
5677 #pragma clang diagnostic ignored "-Wmismatched-tags"
5678#endif
5679template<typename IteratorType>
5680class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5681 : public std::integral_constant<std::size_t, 2> {};
5682
5683template<std::size_t N, typename IteratorType>
5684class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5685{
5686 public:
5687 using type = decltype(
5688 get<N>(std::declval <
5689 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5690};
5691#if defined(__clang__)
5692 #pragma clang diagnostic pop
5693#endif
5694
5695} // namespace std
5696
5697#if JSON_HAS_RANGES
5698 template <typename IteratorType>
5699 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5700#endif
5701
5702// #include <nlohmann/detail/meta/cpp_future.hpp>
5703
5704// #include <nlohmann/detail/meta/std_fs.hpp>
5705
5706// #include <nlohmann/detail/meta/type_traits.hpp>
5707
5708// #include <nlohmann/detail/value_t.hpp>
5709
5710
5712namespace detail
5713{
5714
5716// constructors //
5718
5719/*
5720 * Note all external_constructor<>::construct functions need to call
5721 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5722 * allocated value (e.g., a string). See bug issue
5723 * https://github.com/nlohmann/json/issues/2865 for more information.
5724 */
5725
5726template<value_t> struct external_constructor;
5727
5728template<>
5730{
5731 template<typename BasicJsonType>
5732 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5733 {
5734 j.m_data.m_value.destroy(j.m_data.m_type);
5735 j.m_data.m_type = value_t::boolean;
5736 j.m_data.m_value = b;
5737 j.assert_invariant();
5738 }
5739};
5740
5741template<>
5743{
5744 template<typename BasicJsonType>
5745 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5746 {
5747 j.m_data.m_value.destroy(j.m_data.m_type);
5748 j.m_data.m_type = value_t::string;
5749 j.m_data.m_value = s;
5750 j.assert_invariant();
5751 }
5752
5753 template<typename BasicJsonType>
5754 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5755 {
5756 j.m_data.m_value.destroy(j.m_data.m_type);
5757 j.m_data.m_type = value_t::string;
5758 j.m_data.m_value = std::move(s);
5759 j.assert_invariant();
5760 }
5761
5762 template < typename BasicJsonType, typename CompatibleStringType,
5763 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5764 int > = 0 >
5765 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5766 {
5767 j.m_data.m_value.destroy(j.m_data.m_type);
5768 j.m_data.m_type = value_t::string;
5769 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5770 j.assert_invariant();
5771 }
5772};
5773
5774template<>
5776{
5777 template<typename BasicJsonType>
5778 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5779 {
5780 j.m_data.m_value.destroy(j.m_data.m_type);
5781 j.m_data.m_type = value_t::binary;
5782 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5783 j.assert_invariant();
5784 }
5785
5786 template<typename BasicJsonType>
5787 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5788 {
5789 j.m_data.m_value.destroy(j.m_data.m_type);
5790 j.m_data.m_type = value_t::binary;
5791 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5792 j.assert_invariant();
5793 }
5794};
5795
5796template<>
5798{
5799 template<typename BasicJsonType>
5800 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5801 {
5802 j.m_data.m_value.destroy(j.m_data.m_type);
5803 j.m_data.m_type = value_t::number_float;
5804 j.m_data.m_value = val;
5805 j.assert_invariant();
5806 }
5807};
5808
5809template<>
5811{
5812 template<typename BasicJsonType>
5813 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5814 {
5815 j.m_data.m_value.destroy(j.m_data.m_type);
5816 j.m_data.m_type = value_t::number_unsigned;
5817 j.m_data.m_value = val;
5818 j.assert_invariant();
5819 }
5820};
5821
5822template<>
5824{
5825 template<typename BasicJsonType>
5826 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5827 {
5828 j.m_data.m_value.destroy(j.m_data.m_type);
5829 j.m_data.m_type = value_t::number_integer;
5830 j.m_data.m_value = val;
5831 j.assert_invariant();
5832 }
5833};
5834
5835template<>
5837{
5838 template<typename BasicJsonType>
5839 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5840 {
5841 j.m_data.m_value.destroy(j.m_data.m_type);
5842 j.m_data.m_type = value_t::array;
5843 j.m_data.m_value = arr;
5844 j.set_parents();
5845 j.assert_invariant();
5846 }
5847
5848 template<typename BasicJsonType>
5849 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5850 {
5851 j.m_data.m_value.destroy(j.m_data.m_type);
5852 j.m_data.m_type = value_t::array;
5853 j.m_data.m_value = std::move(arr);
5854 j.set_parents();
5855 j.assert_invariant();
5856 }
5857
5858 template < typename BasicJsonType, typename CompatibleArrayType,
5859 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5860 int > = 0 >
5861 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5862 {
5863 using std::begin;
5864 using std::end;
5865
5866 j.m_data.m_value.destroy(j.m_data.m_type);
5867 j.m_data.m_type = value_t::array;
5868 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5869 j.set_parents();
5870 j.assert_invariant();
5871 }
5872
5873 template<typename BasicJsonType>
5874 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5875 {
5876 j.m_data.m_value.destroy(j.m_data.m_type);
5877 j.m_data.m_type = value_t::array;
5878 j.m_data.m_value = value_t::array;
5879 j.m_data.m_value.array->reserve(arr.size());
5880 for (const bool x : arr)
5881 {
5882 j.m_data.m_value.array->push_back(x);
5883 j.set_parent(j.m_data.m_value.array->back());
5884 }
5885 j.assert_invariant();
5886 }
5887
5888 template<typename BasicJsonType, typename T,
5890 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5891 {
5892 j.m_data.m_value.destroy(j.m_data.m_type);
5893 j.m_data.m_type = value_t::array;
5894 j.m_data.m_value = value_t::array;
5895 j.m_data.m_value.array->resize(arr.size());
5896 if (arr.size() > 0)
5897 {
5898 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5899 }
5900 j.set_parents();
5901 j.assert_invariant();
5902 }
5903};
5904
5905template<>
5907{
5908 template<typename BasicJsonType>
5909 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5910 {
5911 j.m_data.m_value.destroy(j.m_data.m_type);
5912 j.m_data.m_type = value_t::object;
5913 j.m_data.m_value = obj;
5914 j.set_parents();
5915 j.assert_invariant();
5916 }
5917
5918 template<typename BasicJsonType>
5919 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5920 {
5921 j.m_data.m_value.destroy(j.m_data.m_type);
5922 j.m_data.m_type = value_t::object;
5923 j.m_data.m_value = std::move(obj);
5924 j.set_parents();
5925 j.assert_invariant();
5926 }
5927
5928 template < typename BasicJsonType, typename CompatibleObjectType,
5929 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5930 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5931 {
5932 using std::begin;
5933 using std::end;
5934
5935 j.m_data.m_value.destroy(j.m_data.m_type);
5936 j.m_data.m_type = value_t::object;
5937 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5938 j.set_parents();
5939 j.assert_invariant();
5940 }
5941};
5942
5944// to_json //
5946
5947#ifdef JSON_HAS_CPP_17
5948template<typename BasicJsonType, typename T,
5949 enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
5950void to_json(BasicJsonType& j, const std::optional<T>& opt) noexcept
5951{
5952 if (opt.has_value())
5953 {
5954 j = *opt;
5955 }
5956 else
5957 {
5958 j = nullptr;
5959 }
5960}
5961#endif
5962
5963template<typename BasicJsonType, typename T,
5965inline void to_json(BasicJsonType& j, T b) noexcept
5966{
5968}
5969
5970template < typename BasicJsonType, typename BoolRef,
5971 enable_if_t <
5972 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5973 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5974 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5975 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5976 typename BasicJsonType::boolean_t >::value))
5977 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5978inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5979{
5980 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5981}
5982
5983template<typename BasicJsonType, typename CompatibleString,
5984 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5985inline void to_json(BasicJsonType& j, const CompatibleString& s)
5986{
5988}
5989
5990template<typename BasicJsonType>
5991inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5992{
5994}
5995
5996template<typename BasicJsonType, typename FloatType,
5997 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5998inline void to_json(BasicJsonType& j, FloatType val) noexcept
5999{
6000 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
6001}
6002
6003template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
6004 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
6005inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
6006{
6007 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
6008}
6009
6010template<typename BasicJsonType, typename CompatibleNumberIntegerType,
6011 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
6012inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
6013{
6014 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
6015}
6016
6017#if !JSON_DISABLE_ENUM_SERIALIZATION
6018template<typename BasicJsonType, typename EnumType,
6019 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
6020inline void to_json(BasicJsonType& j, EnumType e) noexcept
6021{
6022 using underlying_type = typename std::underlying_type<EnumType>::type;
6023 static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
6024 external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
6025}
6026#endif // JSON_DISABLE_ENUM_SERIALIZATION
6027
6028template<typename BasicJsonType>
6029inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
6030{
6032}
6033
6034template < typename BasicJsonType, typename CompatibleArrayType,
6035 enable_if_t < is_compatible_array_type<BasicJsonType,
6036 CompatibleArrayType>::value&&
6037 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
6039 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
6040 !is_basic_json<CompatibleArrayType>::value,
6041 int > = 0 >
6042inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
6043{
6045}
6046
6047template<typename BasicJsonType>
6048inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
6049{
6051}
6052
6053template<typename BasicJsonType, typename T,
6054 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
6055inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
6056{
6058}
6059
6060template<typename BasicJsonType>
6061inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
6062{
6064}
6065
6066template < typename BasicJsonType, typename CompatibleObjectType,
6067 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
6068inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
6069{
6071}
6072
6073template<typename BasicJsonType>
6074inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
6075{
6077}
6078
6079template <
6080 typename BasicJsonType, typename T, std::size_t N,
6081 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
6082 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6083 int > = 0 >
6084inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6085{
6087}
6088
6089template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
6090inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
6091{
6092 j = { p.first, p.second };
6093}
6094
6095// for https://github.com/nlohmann/json/pull/1134
6096template<typename BasicJsonType, typename T,
6098inline void to_json(BasicJsonType& j, const T& b)
6099{
6100 j = { {b.key(), b.value()} };
6101}
6102
6103template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
6104inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
6105{
6106 j = { std::get<Idx>(t)... };
6107}
6108
6109template<typename BasicJsonType, typename Tuple>
6110inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
6111{
6112 using array_t = typename BasicJsonType::array_t;
6113 j = array_t();
6114}
6115
6116template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
6117inline void to_json(BasicJsonType& j, const T& t)
6118{
6119 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
6120}
6121
6122#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
6123#if defined(__cpp_lib_char8_t)
6124template<typename BasicJsonType, typename Tr, typename Allocator>
6125inline void to_json(BasicJsonType& j, const std::basic_string<char8_t, Tr, Allocator>& s)
6126{
6127 using OtherAllocator = typename std::allocator_traits<Allocator>::template rebind_alloc<char>;
6128 j = std::basic_string<char, std::char_traits<char>, OtherAllocator>(s.begin(), s.end(), s.get_allocator());
6129}
6130#endif
6131
6132template<typename BasicJsonType>
6133inline void to_json(BasicJsonType& j, const std_fs::path& p)
6134{
6135 // Returns either a std::string or a std::u8string depending whether library
6136 // support for char8_t is enabled.
6137 j = p.u8string();
6138}
6139#endif
6140
6142{
6143 template<typename BasicJsonType, typename T>
6144 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
6145 -> decltype(to_json(j, std::forward<T>(val)), void())
6146 {
6147 return to_json(j, std::forward<T>(val));
6148 }
6149};
6150} // namespace detail
6151
6152#ifndef JSON_HAS_CPP_17
6156namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
6157{
6158#endif
6159JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
6161#ifndef JSON_HAS_CPP_17
6162} // namespace
6163#endif
6164
6166
6167// #include <nlohmann/detail/meta/identity_tag.hpp>
6168
6169
6171
6173template<typename ValueType, typename>
6175{
6178 template<typename BasicJsonType, typename TargetType = ValueType>
6179 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
6180 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
6181 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
6182 {
6183 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
6184 }
6185
6188 template<typename BasicJsonType, typename TargetType = ValueType>
6189 static auto from_json(BasicJsonType && j) noexcept(
6190 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
6191 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
6192 {
6193 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
6194 }
6195
6198 template<typename BasicJsonType, typename TargetType = ValueType>
6199 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
6200 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
6201 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
6202 {
6203 ::nlohmann::to_json(j, std::forward<TargetType>(val));
6204 }
6205};
6206
6208
6209// #include <nlohmann/byte_container_with_subtype.hpp>
6210// __ _____ _____ _____
6211// __| | __| | | | JSON for Modern C++
6212// | | |__ | | | | | | version 3.12.0
6213// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6214//
6215// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6216// SPDX-License-Identifier: MIT
6217
6218
6219
6220#include <cstdint> // uint8_t, uint64_t
6221#include <tuple> // tie
6222#include <utility> // move
6223
6224// #include <nlohmann/detail/abi_macros.hpp>
6225
6226
6228
6231template<typename BinaryType>
6232class byte_container_with_subtype : public BinaryType
6233{
6234 public:
6235 using container_type = BinaryType;
6236 using subtype_type = std::uint64_t;
6237
6240 : container_type()
6241 {}
6242
6245 : container_type(b)
6246 {}
6247
6249 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
6250 : container_type(std::move(b))
6251 {}
6252
6255 : container_type(b)
6256 , m_subtype(subtype_)
6257 , m_has_subtype(true)
6258 {}
6259
6261 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
6262 : container_type(std::move(b))
6263 , m_subtype(subtype_)
6264 , m_has_subtype(true)
6265 {}
6266
6268 {
6269 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
6270 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
6271 }
6272
6274 {
6275 return !(rhs == *this);
6276 }
6277
6280 void set_subtype(subtype_type subtype_) noexcept
6281 {
6282 m_subtype = subtype_;
6283 m_has_subtype = true;
6284 }
6285
6288 constexpr subtype_type subtype() const noexcept
6289 {
6290 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
6291 }
6292
6295 constexpr bool has_subtype() const noexcept
6296 {
6297 return m_has_subtype;
6298 }
6299
6302 void clear_subtype() noexcept
6303 {
6304 m_subtype = 0;
6305 m_has_subtype = false;
6306 }
6307
6308 private:
6309 subtype_type m_subtype = 0;
6310 bool m_has_subtype = false;
6311};
6312
6314
6315// #include <nlohmann/detail/conversions/from_json.hpp>
6316
6317// #include <nlohmann/detail/conversions/to_json.hpp>
6318
6319// #include <nlohmann/detail/exceptions.hpp>
6320
6321// #include <nlohmann/detail/hash.hpp>
6322// __ _____ _____ _____
6323// __| | __| | | | JSON for Modern C++
6324// | | |__ | | | | | | version 3.12.0
6325// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6326//
6327// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6328// SPDX-License-Identifier: MIT
6329
6330
6331
6332#include <cstdint> // uint8_t
6333#include <cstddef> // size_t
6334#include <functional> // hash
6335
6336// #include <nlohmann/detail/abi_macros.hpp>
6337
6338// #include <nlohmann/detail/value_t.hpp>
6339
6340
6342namespace detail
6343{
6344
6345// boost::hash_combine
6346inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6347{
6348 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6349 return seed;
6350}
6351
6363template<typename BasicJsonType>
6364std::size_t hash(const BasicJsonType& j)
6365{
6366 using string_t = typename BasicJsonType::string_t;
6367 using number_integer_t = typename BasicJsonType::number_integer_t;
6368 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6369 using number_float_t = typename BasicJsonType::number_float_t;
6370
6371 const auto type = static_cast<std::size_t>(j.type());
6372 switch (j.type())
6373 {
6374 case BasicJsonType::value_t::null:
6375 case BasicJsonType::value_t::discarded:
6376 {
6377 return combine(type, 0);
6378 }
6379
6380 case BasicJsonType::value_t::object:
6381 {
6382 auto seed = combine(type, j.size());
6383 for (const auto& element : j.items())
6384 {
6385 const auto h = std::hash<string_t> {}(element.key());
6386 seed = combine(seed, h);
6387 seed = combine(seed, hash(element.value()));
6388 }
6389 return seed;
6390 }
6391
6392 case BasicJsonType::value_t::array:
6393 {
6394 auto seed = combine(type, j.size());
6395 for (const auto& element : j)
6396 {
6397 seed = combine(seed, hash(element));
6398 }
6399 return seed;
6400 }
6401
6402 case BasicJsonType::value_t::string:
6403 {
6404 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6405 return combine(type, h);
6406 }
6407
6408 case BasicJsonType::value_t::boolean:
6409 {
6410 const auto h = std::hash<bool> {}(j.template get<bool>());
6411 return combine(type, h);
6412 }
6413
6414 case BasicJsonType::value_t::number_integer:
6415 {
6416 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6417 return combine(type, h);
6418 }
6419
6420 case BasicJsonType::value_t::number_unsigned:
6421 {
6422 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6423 return combine(type, h);
6424 }
6425
6426 case BasicJsonType::value_t::number_float:
6427 {
6428 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6429 return combine(type, h);
6430 }
6431
6432 case BasicJsonType::value_t::binary:
6433 {
6434 auto seed = combine(type, j.get_binary().size());
6435 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6436 seed = combine(seed, h);
6437 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6438 for (const auto byte : j.get_binary())
6439 {
6440 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6441 }
6442 return seed;
6443 }
6444
6445 default: // LCOV_EXCL_LINE
6446 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6447 return 0; // LCOV_EXCL_LINE
6448 }
6449}
6450
6451} // namespace detail
6453
6454// #include <nlohmann/detail/input/binary_reader.hpp>
6455// __ _____ _____ _____
6456// __| | __| | | | JSON for Modern C++
6457// | | |__ | | | | | | version 3.12.0
6458// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6459//
6460// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6461// SPDX-License-Identifier: MIT
6462
6463
6464
6465#include <algorithm> // generate_n
6466#include <array> // array
6467#include <cmath> // ldexp
6468#include <cstddef> // size_t
6469#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6470#include <cstdio> // snprintf
6471#include <cstring> // memcpy
6472#include <iterator> // back_inserter
6473#include <limits> // numeric_limits
6474#include <string> // char_traits, string
6475#include <utility> // make_pair, move
6476#include <vector> // vector
6477#ifdef __cpp_lib_byteswap
6478 #include <bit> //byteswap
6479#endif
6480
6481// #include <nlohmann/detail/exceptions.hpp>
6482
6483// #include <nlohmann/detail/input/input_adapters.hpp>
6484// __ _____ _____ _____
6485// __| | __| | | | JSON for Modern C++
6486// | | |__ | | | | | | version 3.12.0
6487// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6488//
6489// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
6490// SPDX-License-Identifier: MIT
6491
6492
6493
6494#include <array> // array
6495#include <cstddef> // size_t
6496#include <cstring> // strlen
6497#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6498#include <memory> // shared_ptr, make_shared, addressof
6499#include <numeric> // accumulate
6500#include <string> // string, char_traits
6501#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6502#include <utility> // pair, declval
6503
6504#ifndef JSON_NO_IO
6505 #include <cstdio> // FILE *
6506 #include <istream> // istream
6507#endif // JSON_NO_IO
6508
6509// #include <nlohmann/detail/exceptions.hpp>
6510
6511// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6512
6513// #include <nlohmann/detail/macro_scope.hpp>
6514
6515// #include <nlohmann/detail/meta/type_traits.hpp>
6516
6517
6519namespace detail
6520{
6521
6524
6526// input adapters //
6528
6529#ifndef JSON_NO_IO
6535{
6536 public:
6537 using char_type = char;
6538
6540 explicit file_input_adapter(std::FILE* f) noexcept
6541 : m_file(f)
6542 {
6543 JSON_ASSERT(m_file != nullptr);
6544 }
6545
6546 // make class move-only
6549 file_input_adapter& operator=(const file_input_adapter&) = delete;
6552
6553 std::char_traits<char>::int_type get_character() noexcept
6554 {
6555 return std::fgetc(m_file);
6556 }
6557
6558 // returns the number of characters successfully read
6559 template<class T>
6560 std::size_t get_elements(T* dest, std::size_t count = 1)
6561 {
6562 return fread(dest, 1, sizeof(T) * count, m_file);
6563 }
6564
6565 private:
6567 std::FILE* m_file;
6568};
6569
6580{
6581 public:
6582 using char_type = char;
6583
6585 {
6586 // clear stream flags; we use underlying streambuf I/O, do not
6587 // maintain ifstream flags, except eof
6588 if (is != nullptr)
6589 {
6590 is->clear(is->rdstate() & std::ios::eofbit);
6591 }
6592 }
6593
6594 explicit input_stream_adapter(std::istream& i)
6595 : is(&i), sb(i.rdbuf())
6596 {}
6597
6598 // deleted because of pointer members
6602
6604 : is(rhs.is), sb(rhs.sb)
6605 {
6606 rhs.is = nullptr;
6607 rhs.sb = nullptr;
6608 }
6609
6610 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6611 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6612 // end up as the same value, e.g., 0xFFFFFFFF.
6613 std::char_traits<char>::int_type get_character()
6614 {
6615 auto res = sb->sbumpc();
6616 // set eof manually, as we don't use the istream interface.
6617 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6618 {
6619 is->clear(is->rdstate() | std::ios::eofbit);
6620 }
6621 return res;
6622 }
6623
6624 template<class T>
6625 std::size_t get_elements(T* dest, std::size_t count = 1)
6626 {
6627 auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
6628 if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
6629 {
6630 is->clear(is->rdstate() | std::ios::eofbit);
6631 }
6632 return res;
6633 }
6634
6635 private:
6637 std::istream* is = nullptr;
6638 std::streambuf* sb = nullptr;
6639};
6640#endif // JSON_NO_IO
6641
6642// General-purpose iterator-based adapter. It might not be as fast as
6643// theoretically possible for some containers, but it is extremely versatile.
6644template<typename IteratorType>
6646{
6647 public:
6648 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6649
6650 iterator_input_adapter(IteratorType first, IteratorType last)
6651 : current(std::move(first)), end(std::move(last))
6652 {}
6653
6655 {
6656 if (JSON_HEDLEY_LIKELY(current != end))
6657 {
6658 auto result = char_traits<char_type>::to_int_type(*current);
6659 std::advance(current, 1);
6660 return result;
6661 }
6662
6664 }
6665
6666 // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
6667 template<class T>
6668 std::size_t get_elements(T* dest, std::size_t count = 1)
6669 {
6670 auto* ptr = reinterpret_cast<char*>(dest);
6671 for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
6672 {
6673 if (JSON_HEDLEY_LIKELY(current != end))
6674 {
6675 ptr[read_index] = static_cast<char>(*current);
6676 std::advance(current, 1);
6677 }
6678 else
6679 {
6680 return read_index;
6681 }
6682 }
6683 return count * sizeof(T);
6684 }
6685
6686 private:
6687 IteratorType current;
6688 IteratorType end;
6689
6690 template<typename BaseInputAdapter, size_t T>
6692
6693 bool empty() const
6694 {
6695 return current == end;
6696 }
6697};
6698
6699template<typename BaseInputAdapter, size_t T>
6701
6702template<typename BaseInputAdapter>
6703struct wide_string_input_helper<BaseInputAdapter, 4>
6704{
6705 // UTF-32
6706 static void fill_buffer(BaseInputAdapter& input,
6707 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6708 size_t& utf8_bytes_index,
6709 size_t& utf8_bytes_filled)
6710 {
6711 utf8_bytes_index = 0;
6712
6713 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6714 {
6715 utf8_bytes[0] = std::char_traits<char>::eof();
6716 utf8_bytes_filled = 1;
6717 }
6718 else
6719 {
6720 // get the current character
6721 const auto wc = input.get_character();
6722
6723 // UTF-32 to UTF-8 encoding
6724 if (wc < 0x80)
6725 {
6726 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6727 utf8_bytes_filled = 1;
6728 }
6729 else if (wc <= 0x7FF)
6730 {
6731 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6732 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6733 utf8_bytes_filled = 2;
6734 }
6735 else if (wc <= 0xFFFF)
6736 {
6737 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6738 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6739 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6740 utf8_bytes_filled = 3;
6741 }
6742 else if (wc <= 0x10FFFF)
6743 {
6744 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6745 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6746 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6747 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6748 utf8_bytes_filled = 4;
6749 }
6750 else
6751 {
6752 // unknown character
6753 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6754 utf8_bytes_filled = 1;
6755 }
6756 }
6757 }
6758};
6759
6760template<typename BaseInputAdapter>
6761struct wide_string_input_helper<BaseInputAdapter, 2>
6762{
6763 // UTF-16
6764 static void fill_buffer(BaseInputAdapter& input,
6765 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6766 size_t& utf8_bytes_index,
6767 size_t& utf8_bytes_filled)
6768 {
6769 utf8_bytes_index = 0;
6770
6771 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6772 {
6773 utf8_bytes[0] = std::char_traits<char>::eof();
6774 utf8_bytes_filled = 1;
6775 }
6776 else
6777 {
6778 // get the current character
6779 const auto wc = input.get_character();
6780
6781 // UTF-16 to UTF-8 encoding
6782 if (wc < 0x80)
6783 {
6784 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6785 utf8_bytes_filled = 1;
6786 }
6787 else if (wc <= 0x7FF)
6788 {
6789 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6790 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6791 utf8_bytes_filled = 2;
6792 }
6793 else if (0xD800 > wc || wc >= 0xE000)
6794 {
6795 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6796 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6797 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6798 utf8_bytes_filled = 3;
6799 }
6800 else
6801 {
6802 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6803 {
6804 const auto wc2 = static_cast<unsigned int>(input.get_character());
6805 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6806 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6807 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6808 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6809 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6810 utf8_bytes_filled = 4;
6811 }
6812 else
6813 {
6814 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6815 utf8_bytes_filled = 1;
6816 }
6817 }
6818 }
6819 }
6820};
6821
6822// Wraps another input adapter to convert wide character types into individual bytes.
6823template<typename BaseInputAdapter, typename WideCharType>
6825{
6826 public:
6827 using char_type = char;
6828
6829 wide_string_input_adapter(BaseInputAdapter base)
6830 : base_adapter(base) {}
6831
6832 typename std::char_traits<char>::int_type get_character() noexcept
6833 {
6834 // check if the buffer needs to be filled
6835 if (utf8_bytes_index == utf8_bytes_filled)
6836 {
6837 fill_buffer<sizeof(WideCharType)>();
6838
6839 JSON_ASSERT(utf8_bytes_filled > 0);
6840 JSON_ASSERT(utf8_bytes_index == 0);
6841 }
6842
6843 // use buffer
6844 JSON_ASSERT(utf8_bytes_filled > 0);
6845 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6846 return utf8_bytes[utf8_bytes_index++];
6847 }
6848
6849 // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
6850 template<class T>
6851 std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
6852 {
6853 JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
6854 }
6855
6856 private:
6857 BaseInputAdapter base_adapter;
6858
6859 template<size_t T>
6860 void fill_buffer()
6861 {
6862 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6863 }
6864
6866 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6867
6869 std::size_t utf8_bytes_index = 0;
6871 std::size_t utf8_bytes_filled = 0;
6872};
6873
6874template<typename IteratorType, typename Enable = void>
6876{
6877 using iterator_type = IteratorType;
6878 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6880
6881 static adapter_type create(IteratorType first, IteratorType last)
6882 {
6883 return adapter_type(std::move(first), std::move(last));
6884 }
6885};
6886
6887template<typename T>
6889{
6890 using value_type = typename std::iterator_traits<T>::value_type;
6891 enum
6892 {
6893 value = sizeof(value_type) > 1
6894 };
6895};
6896
6897template<typename IteratorType>
6899{
6900 using iterator_type = IteratorType;
6901 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6904
6905 static adapter_type create(IteratorType first, IteratorType last)
6906 {
6907 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6908 }
6909};
6910
6911// General purpose iterator-based input
6912template<typename IteratorType>
6914{
6916 return factory_type::create(first, last);
6917}
6918
6919// Convenience shorthand from container to iterator
6920// Enables ADL on begin(container) and end(container)
6921// Encloses the using declarations in namespace for not to leak them to outside scope
6922
6924{
6925
6926using std::begin;
6927using std::end;
6928
6929template<typename ContainerType, typename Enable = void>
6931
6932template<typename ContainerType>
6934 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6935 {
6936 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6937
6938 static adapter_type create(const ContainerType& container)
6939{
6940 return input_adapter(begin(container), end(container));
6941}
6942 };
6943
6944} // namespace container_input_adapter_factory_impl
6945
6946template<typename ContainerType>
6951
6952// specialization for std::string
6953using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
6954
6955#ifndef JSON_NO_IO
6956// Special cases with fast paths
6957inline file_input_adapter input_adapter(std::FILE* file)
6958{
6959 if (file == nullptr)
6960 {
6961 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6962 }
6963 return file_input_adapter(file);
6964}
6965
6966inline input_stream_adapter input_adapter(std::istream& stream)
6967{
6968 return input_stream_adapter(stream);
6969}
6970
6971inline input_stream_adapter input_adapter(std::istream&& stream)
6972{
6973 return input_stream_adapter(stream);
6974}
6975#endif // JSON_NO_IO
6976
6977using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6978
6979// Null-delimited strings, and the like.
6980template < typename CharT,
6981 typename std::enable_if <
6982 std::is_pointer<CharT>::value&&
6983 !std::is_array<CharT>::value&&
6984 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6985 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6986 int >::type = 0 >
6988{
6989 if (b == nullptr)
6990 {
6991 JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
6992 }
6993 auto length = std::strlen(reinterpret_cast<const char*>(b));
6994 const auto* ptr = reinterpret_cast<const char*>(b);
6995 return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
6996}
6997
6998template<typename T, std::size_t N>
6999auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
7000{
7001 return input_adapter(array, array + N);
7002}
7003
7004// This class only handles inputs of input_buffer_adapter type.
7005// It's required so that expressions like {ptr, len} can be implicitly cast
7006// to the correct adapter.
7008{
7009 public:
7010 template < typename CharT,
7011 typename std::enable_if <
7012 std::is_pointer<CharT>::value&&
7013 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
7014 sizeof(typename std::remove_pointer<CharT>::type) == 1,
7015 int >::type = 0 >
7016 span_input_adapter(CharT b, std::size_t l)
7017 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
7018
7019 template<class IteratorType,
7020 typename std::enable_if<
7021 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
7022 int>::type = 0>
7023 span_input_adapter(IteratorType first, IteratorType last)
7024 : ia(input_adapter(first, last)) {}
7025
7027 {
7028 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
7029 }
7030
7031 private:
7033};
7034
7035} // namespace detail
7037
7038// #include <nlohmann/detail/input/json_sax.hpp>
7039// __ _____ _____ _____
7040// __| | __| | | | JSON for Modern C++
7041// | | |__ | | | | | | version 3.12.0
7042// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7043//
7044// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7045// SPDX-License-Identifier: MIT
7046
7047
7048
7049#include <cstddef>
7050#include <string> // string
7051#include <type_traits> // enable_if_t
7052#include <utility> // move
7053#include <vector> // vector
7054
7055// #include <nlohmann/detail/exceptions.hpp>
7056
7057// #include <nlohmann/detail/input/lexer.hpp>
7058// __ _____ _____ _____
7059// __| | __| | | | JSON for Modern C++
7060// | | |__ | | | | | | version 3.12.0
7061// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7062//
7063// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
7064// SPDX-License-Identifier: MIT
7065
7066
7067
7068#include <array> // array
7069#include <clocale> // localeconv
7070#include <cstddef> // size_t
7071#include <cstdio> // snprintf
7072#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7073#include <initializer_list> // initializer_list
7074#include <string> // char_traits, string
7075#include <utility> // move
7076#include <vector> // vector
7077
7078// #include <nlohmann/detail/input/input_adapters.hpp>
7079
7080// #include <nlohmann/detail/input/position_t.hpp>
7081
7082// #include <nlohmann/detail/macro_scope.hpp>
7083
7084// #include <nlohmann/detail/meta/type_traits.hpp>
7085
7086
7088namespace detail
7089{
7090
7092// lexer //
7094
7095template<typename BasicJsonType>
7097{
7098 public:
7120
7124 static const char* token_type_name(const token_type t) noexcept
7125 {
7126 switch (t)
7127 {
7129 return "<uninitialized>";
7131 return "true literal";
7133 return "false literal";
7135 return "null literal";
7137 return "string literal";
7141 return "number literal";
7143 return "'['";
7145 return "'{'";
7147 return "']'";
7149 return "'}'";
7151 return "':'";
7153 return "','";
7155 return "<parse error>";
7157 return "end of input";
7159 return "'[', '{', or a literal";
7160 // LCOV_EXCL_START
7161 default: // catch non-enum values
7162 return "unknown token";
7163 // LCOV_EXCL_STOP
7164 }
7165 }
7166};
7167
7172template<typename BasicJsonType, typename InputAdapterType>
7173class lexer : public lexer_base<BasicJsonType>
7174{
7175 using number_integer_t = typename BasicJsonType::number_integer_t;
7176 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7177 using number_float_t = typename BasicJsonType::number_float_t;
7178 using string_t = typename BasicJsonType::string_t;
7179 using char_type = typename InputAdapterType::char_type;
7180 using char_int_type = typename char_traits<char_type>::int_type;
7181
7182 public:
7184
7185 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7186 : ia(std::move(adapter))
7187 , ignore_comments(ignore_comments_)
7188 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7189 {}
7190
7191 // deleted because of pointer members
7192 lexer(const lexer&) = delete;
7193 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7194 lexer& operator=(lexer&) = delete;
7195 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7196 ~lexer() = default;
7197
7198 private:
7200 // locales
7202
7205 static char get_decimal_point() noexcept
7206 {
7207 const auto* loc = localeconv();
7208 JSON_ASSERT(loc != nullptr);
7209 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7210 }
7211
7213 // scan functions
7215
7231 int get_codepoint()
7232 {
7233 // this function only makes sense after reading `\u`
7234 JSON_ASSERT(current == 'u');
7235 int codepoint = 0;
7236
7237 const auto factors = { 12u, 8u, 4u, 0u };
7238 for (const auto factor : factors)
7239 {
7240 get();
7241
7242 if (current >= '0' && current <= '9')
7243 {
7244 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7245 }
7246 else if (current >= 'A' && current <= 'F')
7247 {
7248 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7249 }
7250 else if (current >= 'a' && current <= 'f')
7251 {
7252 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7253 }
7254 else
7255 {
7256 return -1;
7257 }
7258 }
7259
7260 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7261 return codepoint;
7262 }
7263
7279 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7280 {
7281 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7282 add(current);
7283
7284 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7285 {
7286 get();
7287 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7288 {
7289 add(current);
7290 }
7291 else
7292 {
7293 error_message = "invalid string: ill-formed UTF-8 byte";
7294 return false;
7295 }
7296 }
7297
7298 return true;
7299 }
7300
7316 token_type scan_string()
7317 {
7318 // reset token_buffer (ignore opening quote)
7319 reset();
7320
7321 // we entered the function by reading an open quote
7322 JSON_ASSERT(current == '\"');
7323
7324 while (true)
7325 {
7326 // get the next character
7327 switch (get())
7328 {
7329 // end of file while parsing the string
7330 case char_traits<char_type>::eof():
7331 {
7332 error_message = "invalid string: missing closing quote";
7333 return token_type::parse_error;
7334 }
7335
7336 // closing quote
7337 case '\"':
7338 {
7339 return token_type::value_string;
7340 }
7341
7342 // escapes
7343 case '\\':
7344 {
7345 switch (get())
7346 {
7347 // quotation mark
7348 case '\"':
7349 add('\"');
7350 break;
7351 // reverse solidus
7352 case '\\':
7353 add('\\');
7354 break;
7355 // solidus
7356 case '/':
7357 add('/');
7358 break;
7359 // backspace
7360 case 'b':
7361 add('\b');
7362 break;
7363 // form feed
7364 case 'f':
7365 add('\f');
7366 break;
7367 // line feed
7368 case 'n':
7369 add('\n');
7370 break;
7371 // carriage return
7372 case 'r':
7373 add('\r');
7374 break;
7375 // tab
7376 case 't':
7377 add('\t');
7378 break;
7379
7380 // unicode escapes
7381 case 'u':
7382 {
7383 const int codepoint1 = get_codepoint();
7384 int codepoint = codepoint1; // start with codepoint1
7385
7386 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7387 {
7388 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7389 return token_type::parse_error;
7390 }
7391
7392 // check if code point is a high surrogate
7393 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7394 {
7395 // expect next \uxxxx entry
7396 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7397 {
7398 const int codepoint2 = get_codepoint();
7399
7400 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7401 {
7402 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7403 return token_type::parse_error;
7404 }
7405
7406 // check if codepoint2 is a low surrogate
7407 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7408 {
7409 // overwrite codepoint
7410 codepoint = static_cast<int>(
7411 // high surrogate occupies the most significant 22 bits
7412 (static_cast<unsigned int>(codepoint1) << 10u)
7413 // low surrogate occupies the least significant 15 bits
7414 + static_cast<unsigned int>(codepoint2)
7415 // there is still the 0xD800, 0xDC00, and 0x10000 noise
7416 // in the result, so we have to subtract with:
7417 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7418 - 0x35FDC00u);
7419 }
7420 else
7421 {
7422 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7423 return token_type::parse_error;
7424 }
7425 }
7426 else
7427 {
7428 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7429 return token_type::parse_error;
7430 }
7431 }
7432 else
7433 {
7434 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7435 {
7436 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7437 return token_type::parse_error;
7438 }
7439 }
7440
7441 // the result of the above calculation yields a proper codepoint
7442 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7443
7444 // translate codepoint into bytes
7445 if (codepoint < 0x80)
7446 {
7447 // 1-byte characters: 0xxxxxxx (ASCII)
7448 add(static_cast<char_int_type>(codepoint));
7449 }
7450 else if (codepoint <= 0x7FF)
7451 {
7452 // 2-byte characters: 110xxxxx 10xxxxxx
7453 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7454 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7455 }
7456 else if (codepoint <= 0xFFFF)
7457 {
7458 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7459 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7460 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7461 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7462 }
7463 else
7464 {
7465 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7466 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7467 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7468 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7469 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7470 }
7471
7472 break;
7473 }
7474
7475 // other characters after escape
7476 default:
7477 error_message = "invalid string: forbidden character after backslash";
7478 return token_type::parse_error;
7479 }
7480
7481 break;
7482 }
7483
7484 // invalid control characters
7485 case 0x00:
7486 {
7487 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7488 return token_type::parse_error;
7489 }
7490
7491 case 0x01:
7492 {
7493 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7494 return token_type::parse_error;
7495 }
7496
7497 case 0x02:
7498 {
7499 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7500 return token_type::parse_error;
7501 }
7502
7503 case 0x03:
7504 {
7505 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7506 return token_type::parse_error;
7507 }
7508
7509 case 0x04:
7510 {
7511 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7512 return token_type::parse_error;
7513 }
7514
7515 case 0x05:
7516 {
7517 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7518 return token_type::parse_error;
7519 }
7520
7521 case 0x06:
7522 {
7523 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7524 return token_type::parse_error;
7525 }
7526
7527 case 0x07:
7528 {
7529 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7530 return token_type::parse_error;
7531 }
7532
7533 case 0x08:
7534 {
7535 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7536 return token_type::parse_error;
7537 }
7538
7539 case 0x09:
7540 {
7541 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7542 return token_type::parse_error;
7543 }
7544
7545 case 0x0A:
7546 {
7547 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7548 return token_type::parse_error;
7549 }
7550
7551 case 0x0B:
7552 {
7553 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7554 return token_type::parse_error;
7555 }
7556
7557 case 0x0C:
7558 {
7559 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7560 return token_type::parse_error;
7561 }
7562
7563 case 0x0D:
7564 {
7565 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7566 return token_type::parse_error;
7567 }
7568
7569 case 0x0E:
7570 {
7571 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7572 return token_type::parse_error;
7573 }
7574
7575 case 0x0F:
7576 {
7577 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7578 return token_type::parse_error;
7579 }
7580
7581 case 0x10:
7582 {
7583 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7584 return token_type::parse_error;
7585 }
7586
7587 case 0x11:
7588 {
7589 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7590 return token_type::parse_error;
7591 }
7592
7593 case 0x12:
7594 {
7595 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7596 return token_type::parse_error;
7597 }
7598
7599 case 0x13:
7600 {
7601 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7602 return token_type::parse_error;
7603 }
7604
7605 case 0x14:
7606 {
7607 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7608 return token_type::parse_error;
7609 }
7610
7611 case 0x15:
7612 {
7613 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7614 return token_type::parse_error;
7615 }
7616
7617 case 0x16:
7618 {
7619 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7620 return token_type::parse_error;
7621 }
7622
7623 case 0x17:
7624 {
7625 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7626 return token_type::parse_error;
7627 }
7628
7629 case 0x18:
7630 {
7631 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7632 return token_type::parse_error;
7633 }
7634
7635 case 0x19:
7636 {
7637 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7638 return token_type::parse_error;
7639 }
7640
7641 case 0x1A:
7642 {
7643 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7644 return token_type::parse_error;
7645 }
7646
7647 case 0x1B:
7648 {
7649 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7650 return token_type::parse_error;
7651 }
7652
7653 case 0x1C:
7654 {
7655 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7656 return token_type::parse_error;
7657 }
7658
7659 case 0x1D:
7660 {
7661 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7662 return token_type::parse_error;
7663 }
7664
7665 case 0x1E:
7666 {
7667 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7668 return token_type::parse_error;
7669 }
7670
7671 case 0x1F:
7672 {
7673 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7674 return token_type::parse_error;
7675 }
7676
7677 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
7678 case 0x20:
7679 case 0x21:
7680 case 0x23:
7681 case 0x24:
7682 case 0x25:
7683 case 0x26:
7684 case 0x27:
7685 case 0x28:
7686 case 0x29:
7687 case 0x2A:
7688 case 0x2B:
7689 case 0x2C:
7690 case 0x2D:
7691 case 0x2E:
7692 case 0x2F:
7693 case 0x30:
7694 case 0x31:
7695 case 0x32:
7696 case 0x33:
7697 case 0x34:
7698 case 0x35:
7699 case 0x36:
7700 case 0x37:
7701 case 0x38:
7702 case 0x39:
7703 case 0x3A:
7704 case 0x3B:
7705 case 0x3C:
7706 case 0x3D:
7707 case 0x3E:
7708 case 0x3F:
7709 case 0x40:
7710 case 0x41:
7711 case 0x42:
7712 case 0x43:
7713 case 0x44:
7714 case 0x45:
7715 case 0x46:
7716 case 0x47:
7717 case 0x48:
7718 case 0x49:
7719 case 0x4A:
7720 case 0x4B:
7721 case 0x4C:
7722 case 0x4D:
7723 case 0x4E:
7724 case 0x4F:
7725 case 0x50:
7726 case 0x51:
7727 case 0x52:
7728 case 0x53:
7729 case 0x54:
7730 case 0x55:
7731 case 0x56:
7732 case 0x57:
7733 case 0x58:
7734 case 0x59:
7735 case 0x5A:
7736 case 0x5B:
7737 case 0x5D:
7738 case 0x5E:
7739 case 0x5F:
7740 case 0x60:
7741 case 0x61:
7742 case 0x62:
7743 case 0x63:
7744 case 0x64:
7745 case 0x65:
7746 case 0x66:
7747 case 0x67:
7748 case 0x68:
7749 case 0x69:
7750 case 0x6A:
7751 case 0x6B:
7752 case 0x6C:
7753 case 0x6D:
7754 case 0x6E:
7755 case 0x6F:
7756 case 0x70:
7757 case 0x71:
7758 case 0x72:
7759 case 0x73:
7760 case 0x74:
7761 case 0x75:
7762 case 0x76:
7763 case 0x77:
7764 case 0x78:
7765 case 0x79:
7766 case 0x7A:
7767 case 0x7B:
7768 case 0x7C:
7769 case 0x7D:
7770 case 0x7E:
7771 case 0x7F:
7772 {
7773 add(current);
7774 break;
7775 }
7776
7777 // U+0080..U+07FF: bytes C2..DF 80..BF
7778 case 0xC2:
7779 case 0xC3:
7780 case 0xC4:
7781 case 0xC5:
7782 case 0xC6:
7783 case 0xC7:
7784 case 0xC8:
7785 case 0xC9:
7786 case 0xCA:
7787 case 0xCB:
7788 case 0xCC:
7789 case 0xCD:
7790 case 0xCE:
7791 case 0xCF:
7792 case 0xD0:
7793 case 0xD1:
7794 case 0xD2:
7795 case 0xD3:
7796 case 0xD4:
7797 case 0xD5:
7798 case 0xD6:
7799 case 0xD7:
7800 case 0xD8:
7801 case 0xD9:
7802 case 0xDA:
7803 case 0xDB:
7804 case 0xDC:
7805 case 0xDD:
7806 case 0xDE:
7807 case 0xDF:
7808 {
7809 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
7810 {
7811 return token_type::parse_error;
7812 }
7813 break;
7814 }
7815
7816 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
7817 case 0xE0:
7818 {
7819 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
7820 {
7821 return token_type::parse_error;
7822 }
7823 break;
7824 }
7825
7826 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
7827 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
7828 case 0xE1:
7829 case 0xE2:
7830 case 0xE3:
7831 case 0xE4:
7832 case 0xE5:
7833 case 0xE6:
7834 case 0xE7:
7835 case 0xE8:
7836 case 0xE9:
7837 case 0xEA:
7838 case 0xEB:
7839 case 0xEC:
7840 case 0xEE:
7841 case 0xEF:
7842 {
7843 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
7844 {
7845 return token_type::parse_error;
7846 }
7847 break;
7848 }
7849
7850 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
7851 case 0xED:
7852 {
7853 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
7854 {
7855 return token_type::parse_error;
7856 }
7857 break;
7858 }
7859
7860 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
7861 case 0xF0:
7862 {
7863 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7864 {
7865 return token_type::parse_error;
7866 }
7867 break;
7868 }
7869
7870 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
7871 case 0xF1:
7872 case 0xF2:
7873 case 0xF3:
7874 {
7875 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
7876 {
7877 return token_type::parse_error;
7878 }
7879 break;
7880 }
7881
7882 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
7883 case 0xF4:
7884 {
7885 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
7886 {
7887 return token_type::parse_error;
7888 }
7889 break;
7890 }
7891
7892 // the remaining bytes (80..C1 and F5..FF) are ill-formed
7893 default:
7894 {
7895 error_message = "invalid string: ill-formed UTF-8 byte";
7896 return token_type::parse_error;
7897 }
7898 }
7899 }
7900 }
7901
7906 bool scan_comment()
7907 {
7908 switch (get())
7909 {
7910 // single-line comments skip input until a newline or EOF is read
7911 case '/':
7912 {
7913 while (true)
7914 {
7915 switch (get())
7916 {
7917 case '\n':
7918 case '\r':
7920 case '\0':
7921 return true;
7922
7923 default:
7924 break;
7925 }
7926 }
7927 }
7928
7929 // multi-line comments skip input until */ is read
7930 case '*':
7931 {
7932 while (true)
7933 {
7934 switch (get())
7935 {
7937 case '\0':
7938 {
7939 error_message = "invalid comment; missing closing '*/'";
7940 return false;
7941 }
7942
7943 case '*':
7944 {
7945 switch (get())
7946 {
7947 case '/':
7948 return true;
7949
7950 default:
7951 {
7952 unget();
7953 continue;
7954 }
7955 }
7956 }
7957
7958 default:
7959 continue;
7960 }
7961 }
7962 }
7963
7964 // unexpected character after reading '/'
7965 default:
7966 {
7967 error_message = "invalid comment; expecting '/' or '*' after '/'";
7968 return false;
7969 }
7970 }
7971 }
7972
7974 static void strtof(float& f, const char* str, char** endptr) noexcept
7975 {
7976 f = std::strtof(str, endptr);
7977 }
7978
7980 static void strtof(double& f, const char* str, char** endptr) noexcept
7981 {
7982 f = std::strtod(str, endptr);
7983 }
7984
7986 static void strtof(long double& f, const char* str, char** endptr) noexcept
7987 {
7988 f = std::strtold(str, endptr);
7989 }
7990
8031 token_type scan_number() // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
8032 {
8033 // reset token_buffer to store the number's bytes
8034 reset();
8035
8036 // the type of the parsed number; initially set to unsigned; will be
8037 // changed if minus sign, decimal point, or exponent is read
8038 token_type number_type = token_type::value_unsigned;
8039
8040 // state (init): we just found out we need to scan a number
8041 switch (current)
8042 {
8043 case '-':
8044 {
8045 add(current);
8046 goto scan_number_minus;
8047 }
8048
8049 case '0':
8050 {
8051 add(current);
8052 goto scan_number_zero;
8053 }
8054
8055 case '1':
8056 case '2':
8057 case '3':
8058 case '4':
8059 case '5':
8060 case '6':
8061 case '7':
8062 case '8':
8063 case '9':
8064 {
8065 add(current);
8066 goto scan_number_any1;
8067 }
8068
8069 // all other characters are rejected outside scan_number()
8070 default: // LCOV_EXCL_LINE
8071 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8072 }
8073
8074scan_number_minus:
8075 // state: we just parsed a leading minus sign
8076 number_type = token_type::value_integer;
8077 switch (get())
8078 {
8079 case '0':
8080 {
8081 add(current);
8082 goto scan_number_zero;
8083 }
8084
8085 case '1':
8086 case '2':
8087 case '3':
8088 case '4':
8089 case '5':
8090 case '6':
8091 case '7':
8092 case '8':
8093 case '9':
8094 {
8095 add(current);
8096 goto scan_number_any1;
8097 }
8098
8099 default:
8100 {
8101 error_message = "invalid number; expected digit after '-'";
8102 return token_type::parse_error;
8103 }
8104 }
8105
8106scan_number_zero:
8107 // state: we just parse a zero (maybe with a leading minus sign)
8108 switch (get())
8109 {
8110 case '.':
8111 {
8112 add(decimal_point_char);
8113 decimal_point_position = token_buffer.size() - 1;
8114 goto scan_number_decimal1;
8115 }
8116
8117 case 'e':
8118 case 'E':
8119 {
8120 add(current);
8121 goto scan_number_exponent;
8122 }
8123
8124 default:
8125 goto scan_number_done;
8126 }
8127
8128scan_number_any1:
8129 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8130 switch (get())
8131 {
8132 case '0':
8133 case '1':
8134 case '2':
8135 case '3':
8136 case '4':
8137 case '5':
8138 case '6':
8139 case '7':
8140 case '8':
8141 case '9':
8142 {
8143 add(current);
8144 goto scan_number_any1;
8145 }
8146
8147 case '.':
8148 {
8149 add(decimal_point_char);
8150 decimal_point_position = token_buffer.size() - 1;
8151 goto scan_number_decimal1;
8152 }
8153
8154 case 'e':
8155 case 'E':
8156 {
8157 add(current);
8158 goto scan_number_exponent;
8159 }
8160
8161 default:
8162 goto scan_number_done;
8163 }
8164
8165scan_number_decimal1:
8166 // state: we just parsed a decimal point
8167 number_type = token_type::value_float;
8168 switch (get())
8169 {
8170 case '0':
8171 case '1':
8172 case '2':
8173 case '3':
8174 case '4':
8175 case '5':
8176 case '6':
8177 case '7':
8178 case '8':
8179 case '9':
8180 {
8181 add(current);
8182 goto scan_number_decimal2;
8183 }
8184
8185 default:
8186 {
8187 error_message = "invalid number; expected digit after '.'";
8188 return token_type::parse_error;
8189 }
8190 }
8191
8192scan_number_decimal2:
8193 // we just parsed at least one number after a decimal point
8194 switch (get())
8195 {
8196 case '0':
8197 case '1':
8198 case '2':
8199 case '3':
8200 case '4':
8201 case '5':
8202 case '6':
8203 case '7':
8204 case '8':
8205 case '9':
8206 {
8207 add(current);
8208 goto scan_number_decimal2;
8209 }
8210
8211 case 'e':
8212 case 'E':
8213 {
8214 add(current);
8215 goto scan_number_exponent;
8216 }
8217
8218 default:
8219 goto scan_number_done;
8220 }
8221
8222scan_number_exponent:
8223 // we just parsed an exponent
8224 number_type = token_type::value_float;
8225 switch (get())
8226 {
8227 case '+':
8228 case '-':
8229 {
8230 add(current);
8231 goto scan_number_sign;
8232 }
8233
8234 case '0':
8235 case '1':
8236 case '2':
8237 case '3':
8238 case '4':
8239 case '5':
8240 case '6':
8241 case '7':
8242 case '8':
8243 case '9':
8244 {
8245 add(current);
8246 goto scan_number_any2;
8247 }
8248
8249 default:
8250 {
8251 error_message =
8252 "invalid number; expected '+', '-', or digit after exponent";
8253 return token_type::parse_error;
8254 }
8255 }
8256
8257scan_number_sign:
8258 // we just parsed an exponent sign
8259 switch (get())
8260 {
8261 case '0':
8262 case '1':
8263 case '2':
8264 case '3':
8265 case '4':
8266 case '5':
8267 case '6':
8268 case '7':
8269 case '8':
8270 case '9':
8271 {
8272 add(current);
8273 goto scan_number_any2;
8274 }
8275
8276 default:
8277 {
8278 error_message = "invalid number; expected digit after exponent sign";
8279 return token_type::parse_error;
8280 }
8281 }
8282
8283scan_number_any2:
8284 // we just parsed a number after the exponent or exponent sign
8285 switch (get())
8286 {
8287 case '0':
8288 case '1':
8289 case '2':
8290 case '3':
8291 case '4':
8292 case '5':
8293 case '6':
8294 case '7':
8295 case '8':
8296 case '9':
8297 {
8298 add(current);
8299 goto scan_number_any2;
8300 }
8301
8302 default:
8303 goto scan_number_done;
8304 }
8305
8306scan_number_done:
8307 // unget the character after the number (we only read it to know that
8308 // we are done scanning a number)
8309 unget();
8310
8311 char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8312 errno = 0;
8313
8314 // try to parse integers first and fall back to floats
8315 if (number_type == token_type::value_unsigned)
8316 {
8317 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8318
8319 // we checked the number format before
8320 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8321
8322 if (errno != ERANGE)
8323 {
8324 value_unsigned = static_cast<number_unsigned_t>(x);
8325 if (value_unsigned == x)
8326 {
8327 return token_type::value_unsigned;
8328 }
8329 }
8330 }
8331 else if (number_type == token_type::value_integer)
8332 {
8333 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8334
8335 // we checked the number format before
8336 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8337
8338 if (errno != ERANGE)
8339 {
8340 value_integer = static_cast<number_integer_t>(x);
8341 if (value_integer == x)
8342 {
8343 return token_type::value_integer;
8344 }
8345 }
8346 }
8347
8348 // this code is reached if we parse a floating-point number or if an
8349 // integer conversion above failed
8350 strtof(value_float, token_buffer.data(), &endptr);
8351
8352 // we checked the number format before
8353 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8354
8355 return token_type::value_float;
8356 }
8357
8364 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8365 token_type return_type)
8366 {
8367 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8368 for (std::size_t i = 1; i < length; ++i)
8369 {
8371 {
8372 error_message = "invalid literal";
8373 return token_type::parse_error;
8374 }
8375 }
8376 return return_type;
8377 }
8378
8380 // input management
8382
8384 void reset() noexcept
8385 {
8386 token_buffer.clear();
8387 token_string.clear();
8388 decimal_point_position = std::string::npos;
8389 token_string.push_back(char_traits<char_type>::to_char_type(current));
8390 }
8391
8392 /*
8393 @brief get next character from the input
8394
8395 This function provides the interface to the used input adapter. It does
8396 not throw in case the input reached EOF, but returns a
8397 `char_traits<char>::eof()` in that case. Stores the scanned characters
8398 for use in error messages.
8399
8400 @return character read from the input
8401 */
8402 char_int_type get()
8403 {
8404 ++position.chars_read_total;
8405 ++position.chars_read_current_line;
8406
8407 if (next_unget)
8408 {
8409 // only reset the next_unget variable and work with current
8410 next_unget = false;
8411 }
8412 else
8413 {
8414 current = ia.get_character();
8415 }
8416
8418 {
8419 token_string.push_back(char_traits<char_type>::to_char_type(current));
8420 }
8421
8422 if (current == '\n')
8423 {
8424 ++position.lines_read;
8425 position.chars_read_current_line = 0;
8426 }
8427
8428 return current;
8429 }
8430
8439 void unget()
8440 {
8441 next_unget = true;
8442
8443 --position.chars_read_total;
8444
8445 // in case we "unget" a newline, we have to also decrement the lines_read
8446 if (position.chars_read_current_line == 0)
8447 {
8448 if (position.lines_read > 0)
8449 {
8450 --position.lines_read;
8451 }
8452 }
8453 else
8454 {
8455 --position.chars_read_current_line;
8456 }
8457
8459 {
8460 JSON_ASSERT(!token_string.empty());
8461 token_string.pop_back();
8462 }
8463 }
8464
8466 void add(char_int_type c)
8467 {
8468 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8469 }
8470
8471 public:
8473 // value getters
8475
8477 constexpr number_integer_t get_number_integer() const noexcept
8478 {
8479 return value_integer;
8480 }
8481
8483 constexpr number_unsigned_t get_number_unsigned() const noexcept
8484 {
8485 return value_unsigned;
8486 }
8487
8489 constexpr number_float_t get_number_float() const noexcept
8490 {
8491 return value_float;
8492 }
8493
8495 string_t& get_string()
8496 {
8497 // translate decimal points from locale back to '.' (#4084)
8498 if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
8499 {
8500 token_buffer[decimal_point_position] = '.';
8501 }
8502 return token_buffer;
8503 }
8504
8506 // diagnostics
8508
8510 constexpr position_t get_position() const noexcept
8511 {
8512 return position;
8513 }
8514
8518 std::string get_token_string() const
8519 {
8520 // escape control characters
8521 std::string result;
8522 for (const auto c : token_string)
8523 {
8524 if (static_cast<unsigned char>(c) <= '\x1F')
8525 {
8526 // escape control characters
8527 std::array<char, 9> cs{{}};
8528 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8529 result += cs.data();
8530 }
8531 else
8532 {
8533 // add character as is
8534 result.push_back(static_cast<std::string::value_type>(c));
8535 }
8536 }
8537
8538 return result;
8539 }
8540
8543 constexpr const char* get_error_message() const noexcept
8544 {
8545 return error_message;
8546 }
8547
8549 // actual scanner
8551
8557 {
8558 if (get() == 0xEF)
8559 {
8560 // check if we completely parse the BOM
8561 return get() == 0xBB && get() == 0xBF;
8562 }
8563
8564 // the first character is not the beginning of the BOM; unget it to
8565 // process is later
8566 unget();
8567 return true;
8568 }
8569
8571 {
8572 do
8573 {
8574 get();
8575 }
8576 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8577 }
8578
8580 {
8581 // initially, skip the BOM
8582 if (position.chars_read_total == 0 && !skip_bom())
8583 {
8584 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8585 return token_type::parse_error;
8586 }
8587
8588 // read the next character and ignore whitespace
8590
8591 // ignore comments
8592 while (ignore_comments && current == '/')
8593 {
8594 if (!scan_comment())
8595 {
8596 return token_type::parse_error;
8597 }
8598
8599 // skip following whitespace
8601 }
8602
8603 switch (current)
8604 {
8605 // structural characters
8606 case '[':
8607 return token_type::begin_array;
8608 case ']':
8609 return token_type::end_array;
8610 case '{':
8611 return token_type::begin_object;
8612 case '}':
8613 return token_type::end_object;
8614 case ':':
8615 return token_type::name_separator;
8616 case ',':
8617 return token_type::value_separator;
8618
8619 // literals
8620 case 't':
8621 {
8622 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
8623 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8624 }
8625 case 'f':
8626 {
8627 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
8628 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8629 }
8630 case 'n':
8631 {
8632 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
8633 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8634 }
8635
8636 // string
8637 case '\"':
8638 return scan_string();
8639
8640 // number
8641 case '-':
8642 case '0':
8643 case '1':
8644 case '2':
8645 case '3':
8646 case '4':
8647 case '5':
8648 case '6':
8649 case '7':
8650 case '8':
8651 case '9':
8652 return scan_number();
8653
8654 // end of input (the null byte is needed when parsing from
8655 // string literals)
8656 case '\0':
8658 return token_type::end_of_input;
8659
8660 // error
8661 default:
8662 error_message = "invalid literal";
8663 return token_type::parse_error;
8664 }
8665 }
8666
8667 private:
8669 InputAdapterType ia;
8670
8672 const bool ignore_comments = false;
8673
8675 char_int_type current = char_traits<char_type>::eof();
8676
8678 bool next_unget = false;
8679
8681 position_t position {};
8682
8684 std::vector<char_type> token_string {};
8685
8687 string_t token_buffer {};
8688
8690 const char* error_message = "";
8691
8692 // number values
8693 number_integer_t value_integer = 0;
8694 number_unsigned_t value_unsigned = 0;
8695 number_float_t value_float = 0;
8696
8698 const char_int_type decimal_point_char = '.';
8700 std::size_t decimal_point_position = std::string::npos;
8701};
8702
8703} // namespace detail
8705
8706// #include <nlohmann/detail/macro_scope.hpp>
8707
8708// #include <nlohmann/detail/string_concat.hpp>
8709
8711
8720template<typename BasicJsonType>
8722{
8723 using number_integer_t = typename BasicJsonType::number_integer_t;
8724 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8725 using number_float_t = typename BasicJsonType::number_float_t;
8726 using string_t = typename BasicJsonType::string_t;
8727 using binary_t = typename BasicJsonType::binary_t;
8728
8733 virtual bool null() = 0;
8734
8740 virtual bool boolean(bool val) = 0;
8741
8747 virtual bool number_integer(number_integer_t val) = 0;
8748
8754 virtual bool number_unsigned(number_unsigned_t val) = 0;
8755
8762 virtual bool number_float(number_float_t val, const string_t& s) = 0;
8763
8770 virtual bool string(string_t& val) = 0;
8771
8778 virtual bool binary(binary_t& val) = 0;
8779
8786 virtual bool start_object(std::size_t elements) = 0;
8787
8794 virtual bool key(string_t& val) = 0;
8795
8800 virtual bool end_object() = 0;
8801
8808 virtual bool start_array(std::size_t elements) = 0;
8809
8814 virtual bool end_array() = 0;
8815
8823 virtual bool parse_error(std::size_t position,
8824 const std::string& last_token,
8825 const detail::exception& ex) = 0;
8826
8827 json_sax() = default;
8828 json_sax(const json_sax&) = default;
8829 json_sax(json_sax&&) noexcept = default;
8830 json_sax& operator=(const json_sax&) = default;
8831 json_sax& operator=(json_sax&&) noexcept = default;
8832 virtual ~json_sax() = default;
8833};
8834
8835namespace detail
8836{
8837constexpr std::size_t unknown_size()
8838{
8839 return (std::numeric_limits<std::size_t>::max)();
8840}
8841
8855template<typename BasicJsonType, typename InputAdapterType>
8857{
8858 public:
8859 using number_integer_t = typename BasicJsonType::number_integer_t;
8860 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
8861 using number_float_t = typename BasicJsonType::number_float_t;
8862 using string_t = typename BasicJsonType::string_t;
8863 using binary_t = typename BasicJsonType::binary_t;
8865
8871 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
8872 : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
8873 {}
8874
8875 // make class move-only
8877 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8879 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
8881
8882 bool null()
8883 {
8884 handle_value(nullptr);
8885 return true;
8886 }
8887
8888 bool boolean(bool val)
8889 {
8890 handle_value(val);
8891 return true;
8892 }
8893
8895 {
8896 handle_value(val);
8897 return true;
8898 }
8899
8901 {
8902 handle_value(val);
8903 return true;
8904 }
8905
8906 bool number_float(number_float_t val, const string_t& /*unused*/)
8907 {
8908 handle_value(val);
8909 return true;
8910 }
8911
8912 bool string(string_t& val)
8913 {
8914 handle_value(val);
8915 return true;
8916 }
8917
8918 bool binary(binary_t& val)
8919 {
8920 handle_value(std::move(val));
8921 return true;
8922 }
8923
8924 bool start_object(std::size_t len)
8925 {
8926 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
8927
8928#if JSON_DIAGNOSTIC_POSITIONS
8929 // Manually set the start position of the object here.
8930 // Ensure this is after the call to handle_value to ensure correct start position.
8931 if (m_lexer_ref)
8932 {
8933 // Lexer has read the first character of the object, so
8934 // subtract 1 from the position to get the correct start position.
8935 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8936 }
8937#endif
8938
8939 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8940 {
8941 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
8942 }
8943
8944 return true;
8945 }
8946
8947 bool key(string_t& val)
8948 {
8949 JSON_ASSERT(!ref_stack.empty());
8950 JSON_ASSERT(ref_stack.back()->is_object());
8951
8952 // add null at the given key and store the reference for later
8953 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
8954 return true;
8955 }
8956
8958 {
8959 JSON_ASSERT(!ref_stack.empty());
8960 JSON_ASSERT(ref_stack.back()->is_object());
8961
8962#if JSON_DIAGNOSTIC_POSITIONS
8963 if (m_lexer_ref)
8964 {
8965 // Lexer's position is past the closing brace, so set that as the end position.
8966 ref_stack.back()->end_position = m_lexer_ref->get_position();
8967 }
8968#endif
8969
8970 ref_stack.back()->set_parents();
8971 ref_stack.pop_back();
8972 return true;
8973 }
8974
8975 bool start_array(std::size_t len)
8976 {
8977 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
8978
8979#if JSON_DIAGNOSTIC_POSITIONS
8980 // Manually set the start position of the array here.
8981 // Ensure this is after the call to handle_value to ensure correct start position.
8982 if (m_lexer_ref)
8983 {
8984 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
8985 }
8986#endif
8987
8988 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
8989 {
8990 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
8991 }
8992
8993 return true;
8994 }
8995
8997 {
8998 JSON_ASSERT(!ref_stack.empty());
8999 JSON_ASSERT(ref_stack.back()->is_array());
9000
9001#if JSON_DIAGNOSTIC_POSITIONS
9002 if (m_lexer_ref)
9003 {
9004 // Lexer's position is past the closing bracket, so set that as the end position.
9005 ref_stack.back()->end_position = m_lexer_ref->get_position();
9006 }
9007#endif
9008
9009 ref_stack.back()->set_parents();
9010 ref_stack.pop_back();
9011 return true;
9012 }
9013
9014 template<class Exception>
9015 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9016 const Exception& ex)
9017 {
9018 errored = true;
9019 static_cast<void>(ex);
9020 if (allow_exceptions)
9021 {
9022 JSON_THROW(ex);
9023 }
9024 return false;
9025 }
9026
9027 constexpr bool is_errored() const
9028 {
9029 return errored;
9030 }
9031
9032 private:
9033
9034#if JSON_DIAGNOSTIC_POSITIONS
9035 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9036 {
9037 if (m_lexer_ref)
9038 {
9039 // Lexer has read past the current field value, so set the end position to the current position.
9040 // The start position will be set below based on the length of the string representation
9041 // of the value.
9042 v.end_position = m_lexer_ref->get_position();
9043
9044 switch (v.type())
9045 {
9046 case value_t::boolean:
9047 {
9048 // 4 and 5 are the string length of "true" and "false"
9049 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9050 break;
9051 }
9052
9053 case value_t::null:
9054 {
9055 // 4 is the string length of "null"
9056 v.start_position = v.end_position - 4;
9057 break;
9058 }
9059
9060 case value_t::string:
9061 {
9062 // include the length of the quotes, which is 2
9063 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9064 break;
9065 }
9066
9067 // As we handle the start and end positions for values created during parsing,
9068 // we do not expect the following value type to be called. Regardless, set the positions
9069 // in case this is created manually or through a different constructor. Exclude from lcov
9070 // since the exact condition of this switch is esoteric.
9071 // LCOV_EXCL_START
9072 case value_t::discarded:
9073 {
9074 v.end_position = std::string::npos;
9075 v.start_position = v.end_position;
9076 break;
9077 }
9078 // LCOV_EXCL_STOP
9079 case value_t::binary:
9080 case value_t::number_integer:
9081 case value_t::number_unsigned:
9082 case value_t::number_float:
9083 {
9084 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9085 break;
9086 }
9087 case value_t::object:
9088 case value_t::array:
9089 {
9090 // object and array are handled in start_object() and start_array() handlers
9091 // skip setting the values here.
9092 break;
9093 }
9094 default: // LCOV_EXCL_LINE
9095 // Handle all possible types discretely, default handler should never be reached.
9096 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9097 }
9098 }
9099 }
9100#endif
9101
9108 template<typename Value>
9110 BasicJsonType* handle_value(Value&& v)
9111 {
9112 if (ref_stack.empty())
9113 {
9114 root = BasicJsonType(std::forward<Value>(v));
9115
9116#if JSON_DIAGNOSTIC_POSITIONS
9117 handle_diagnostic_positions_for_json_value(root);
9118#endif
9119
9120 return &root;
9121 }
9122
9123 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9124
9125 if (ref_stack.back()->is_array())
9126 {
9127 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
9128
9129#if JSON_DIAGNOSTIC_POSITIONS
9130 handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
9131#endif
9132
9133 return &(ref_stack.back()->m_data.m_value.array->back());
9134 }
9135
9136 JSON_ASSERT(ref_stack.back()->is_object());
9137 JSON_ASSERT(object_element);
9138 *object_element = BasicJsonType(std::forward<Value>(v));
9139
9140#if JSON_DIAGNOSTIC_POSITIONS
9141 handle_diagnostic_positions_for_json_value(*object_element);
9142#endif
9143
9144 return object_element;
9145 }
9146
9148 BasicJsonType& root;
9150 std::vector<BasicJsonType*> ref_stack {};
9152 BasicJsonType* object_element = nullptr;
9154 bool errored = false;
9156 const bool allow_exceptions = true;
9158 lexer_t* m_lexer_ref = nullptr;
9159};
9160
9161template<typename BasicJsonType, typename InputAdapterType>
9163{
9164 public:
9165 using number_integer_t = typename BasicJsonType::number_integer_t;
9166 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9167 using number_float_t = typename BasicJsonType::number_float_t;
9168 using string_t = typename BasicJsonType::string_t;
9169 using binary_t = typename BasicJsonType::binary_t;
9170 using parser_callback_t = typename BasicJsonType::parser_callback_t;
9171 using parse_event_t = typename BasicJsonType::parse_event_t;
9173
9176 const bool allow_exceptions_ = true,
9177 lexer_t* lexer_ = nullptr)
9178 : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
9179 {
9180 keep_stack.push_back(true);
9181 }
9182
9183 // make class move-only
9185 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9187 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9189
9190 bool null()
9191 {
9192 handle_value(nullptr);
9193 return true;
9194 }
9195
9196 bool boolean(bool val)
9197 {
9198 handle_value(val);
9199 return true;
9200 }
9201
9203 {
9204 handle_value(val);
9205 return true;
9206 }
9207
9209 {
9210 handle_value(val);
9211 return true;
9212 }
9213
9214 bool number_float(number_float_t val, const string_t& /*unused*/)
9215 {
9216 handle_value(val);
9217 return true;
9218 }
9219
9220 bool string(string_t& val)
9221 {
9222 handle_value(val);
9223 return true;
9224 }
9225
9226 bool binary(binary_t& val)
9227 {
9228 handle_value(std::move(val));
9229 return true;
9230 }
9231
9232 bool start_object(std::size_t len)
9233 {
9234 // check callback for object start
9235 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
9236 keep_stack.push_back(keep);
9237
9238 auto val = handle_value(BasicJsonType::value_t::object, true);
9239 ref_stack.push_back(val.second);
9240
9241 if (ref_stack.back())
9242 {
9243
9244#if JSON_DIAGNOSTIC_POSITIONS
9245 // Manually set the start position of the object here.
9246 // Ensure this is after the call to handle_value to ensure correct start position.
9247 if (m_lexer_ref)
9248 {
9249 // Lexer has read the first character of the object, so
9250 // subtract 1 from the position to get the correct start position.
9251 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9252 }
9253#endif
9254
9255 // check object limit
9256 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9257 {
9258 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
9259 }
9260 }
9261 return true;
9262 }
9263
9264 bool key(string_t& val)
9265 {
9266 BasicJsonType k = BasicJsonType(val);
9267
9268 // check callback for the key
9269 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
9270 key_keep_stack.push_back(keep);
9271
9272 // add discarded value at the given key and store the reference for later
9273 if (keep && ref_stack.back())
9274 {
9275 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
9276 }
9277
9278 return true;
9279 }
9280
9282 {
9283 if (ref_stack.back())
9284 {
9285 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
9286 {
9287 // discard object
9288 *ref_stack.back() = discarded;
9289
9290#if JSON_DIAGNOSTIC_POSITIONS
9291 // Set start/end positions for discarded object.
9292 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9293#endif
9294 }
9295 else
9296 {
9297
9298#if JSON_DIAGNOSTIC_POSITIONS
9299 if (m_lexer_ref)
9300 {
9301 // Lexer's position is past the closing brace, so set that as the end position.
9302 ref_stack.back()->end_position = m_lexer_ref->get_position();
9303 }
9304#endif
9305
9306 ref_stack.back()->set_parents();
9307 }
9308 }
9309
9310 JSON_ASSERT(!ref_stack.empty());
9311 JSON_ASSERT(!keep_stack.empty());
9312 ref_stack.pop_back();
9313 keep_stack.pop_back();
9314
9315 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
9316 {
9317 // remove discarded value
9318 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
9319 {
9320 if (it->is_discarded())
9321 {
9322 ref_stack.back()->erase(it);
9323 break;
9324 }
9325 }
9326 }
9327
9328 return true;
9329 }
9330
9331 bool start_array(std::size_t len)
9332 {
9333 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
9334 keep_stack.push_back(keep);
9335
9336 auto val = handle_value(BasicJsonType::value_t::array, true);
9337 ref_stack.push_back(val.second);
9338
9339 if (ref_stack.back())
9340 {
9341
9342#if JSON_DIAGNOSTIC_POSITIONS
9343 // Manually set the start position of the array here.
9344 // Ensure this is after the call to handle_value to ensure correct start position.
9345 if (m_lexer_ref)
9346 {
9347 // Lexer has read the first character of the array, so
9348 // subtract 1 from the position to get the correct start position.
9349 ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
9350 }
9351#endif
9352
9353 // check array limit
9354 if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
9355 {
9356 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
9357 }
9358 }
9359
9360 return true;
9361 }
9362
9364 {
9365 bool keep = true;
9366
9367 if (ref_stack.back())
9368 {
9369 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
9370 if (keep)
9371 {
9372
9373#if JSON_DIAGNOSTIC_POSITIONS
9374 if (m_lexer_ref)
9375 {
9376 // Lexer's position is past the closing bracket, so set that as the end position.
9377 ref_stack.back()->end_position = m_lexer_ref->get_position();
9378 }
9379#endif
9380
9381 ref_stack.back()->set_parents();
9382 }
9383 else
9384 {
9385 // discard array
9386 *ref_stack.back() = discarded;
9387
9388#if JSON_DIAGNOSTIC_POSITIONS
9389 // Set start/end positions for discarded array.
9390 handle_diagnostic_positions_for_json_value(*ref_stack.back());
9391#endif
9392 }
9393 }
9394
9395 JSON_ASSERT(!ref_stack.empty());
9396 JSON_ASSERT(!keep_stack.empty());
9397 ref_stack.pop_back();
9398 keep_stack.pop_back();
9399
9400 // remove discarded value
9401 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
9402 {
9403 ref_stack.back()->m_data.m_value.array->pop_back();
9404 }
9405
9406 return true;
9407 }
9408
9409 template<class Exception>
9410 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
9411 const Exception& ex)
9412 {
9413 errored = true;
9414 static_cast<void>(ex);
9415 if (allow_exceptions)
9416 {
9417 JSON_THROW(ex);
9418 }
9419 return false;
9420 }
9421
9422 constexpr bool is_errored() const
9423 {
9424 return errored;
9425 }
9426
9427 private:
9428
9429#if JSON_DIAGNOSTIC_POSITIONS
9430 void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
9431 {
9432 if (m_lexer_ref)
9433 {
9434 // Lexer has read past the current field value, so set the end position to the current position.
9435 // The start position will be set below based on the length of the string representation
9436 // of the value.
9437 v.end_position = m_lexer_ref->get_position();
9438
9439 switch (v.type())
9440 {
9441 case value_t::boolean:
9442 {
9443 // 4 and 5 are the string length of "true" and "false"
9444 v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
9445 break;
9446 }
9447
9448 case value_t::null:
9449 {
9450 // 4 is the string length of "null"
9451 v.start_position = v.end_position - 4;
9452 break;
9453 }
9454
9455 case value_t::string:
9456 {
9457 // include the length of the quotes, which is 2
9458 v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
9459 break;
9460 }
9461
9462 case value_t::discarded:
9463 {
9464 v.end_position = std::string::npos;
9465 v.start_position = v.end_position;
9466 break;
9467 }
9468
9469 case value_t::binary:
9470 case value_t::number_integer:
9471 case value_t::number_unsigned:
9472 case value_t::number_float:
9473 {
9474 v.start_position = v.end_position - m_lexer_ref->get_string().size();
9475 break;
9476 }
9477
9478 case value_t::object:
9479 case value_t::array:
9480 {
9481 // object and array are handled in start_object() and start_array() handlers
9482 // skip setting the values here.
9483 break;
9484 }
9485 default: // LCOV_EXCL_LINE
9486 // Handle all possible types discretely, default handler should never be reached.
9487 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
9488 }
9489 }
9490 }
9491#endif
9492
9508 template<typename Value>
9509 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
9510 {
9511 JSON_ASSERT(!keep_stack.empty());
9512
9513 // do not handle this value if we know it would be added to a discarded
9514 // container
9515 if (!keep_stack.back())
9516 {
9517 return {false, nullptr};
9518 }
9519
9520 // create value
9521 auto value = BasicJsonType(std::forward<Value>(v));
9522
9523#if JSON_DIAGNOSTIC_POSITIONS
9524 handle_diagnostic_positions_for_json_value(value);
9525#endif
9526
9527 // check callback
9528 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
9529
9530 // do not handle this value if we just learnt it shall be discarded
9531 if (!keep)
9532 {
9533 return {false, nullptr};
9534 }
9535
9536 if (ref_stack.empty())
9537 {
9538 root = std::move(value);
9539 return {true, & root};
9540 }
9541
9542 // skip this value if we already decided to skip the parent
9543 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
9544 if (!ref_stack.back())
9545 {
9546 return {false, nullptr};
9547 }
9548
9549 // we now only expect arrays and objects
9550 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
9551
9552 // array
9553 if (ref_stack.back()->is_array())
9554 {
9555 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
9556 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
9557 }
9558
9559 // object
9560 JSON_ASSERT(ref_stack.back()->is_object());
9561 // check if we should store an element for the current key
9562 JSON_ASSERT(!key_keep_stack.empty());
9563 const bool store_element = key_keep_stack.back();
9564 key_keep_stack.pop_back();
9565
9566 if (!store_element)
9567 {
9568 return {false, nullptr};
9569 }
9570
9571 JSON_ASSERT(object_element);
9572 *object_element = std::move(value);
9573 return {true, object_element};
9574 }
9575
9577 BasicJsonType& root;
9579 std::vector<BasicJsonType*> ref_stack {};
9581 std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
9583 std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
9585 BasicJsonType* object_element = nullptr;
9587 bool errored = false;
9589 const parser_callback_t callback = nullptr;
9591 const bool allow_exceptions = true;
9593 BasicJsonType discarded = BasicJsonType::value_t::discarded;
9595 lexer_t* m_lexer_ref = nullptr;
9596};
9597
9598template<typename BasicJsonType>
9600{
9601 public:
9602 using number_integer_t = typename BasicJsonType::number_integer_t;
9603 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9604 using number_float_t = typename BasicJsonType::number_float_t;
9605 using string_t = typename BasicJsonType::string_t;
9606 using binary_t = typename BasicJsonType::binary_t;
9607
9608 bool null()
9609 {
9610 return true;
9611 }
9612
9613 bool boolean(bool /*unused*/)
9614 {
9615 return true;
9616 }
9617
9619 {
9620 return true;
9621 }
9622
9624 {
9625 return true;
9626 }
9627
9628 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
9629 {
9630 return true;
9631 }
9632
9633 bool string(string_t& /*unused*/)
9634 {
9635 return true;
9636 }
9637
9638 bool binary(binary_t& /*unused*/)
9639 {
9640 return true;
9641 }
9642
9643 bool start_object(std::size_t /*unused*/ = detail::unknown_size())
9644 {
9645 return true;
9646 }
9647
9648 bool key(string_t& /*unused*/)
9649 {
9650 return true;
9651 }
9652
9654 {
9655 return true;
9656 }
9657
9658 bool start_array(std::size_t /*unused*/ = detail::unknown_size())
9659 {
9660 return true;
9661 }
9662
9664 {
9665 return true;
9666 }
9667
9668 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
9669 {
9670 return false;
9671 }
9672};
9673
9674} // namespace detail
9676
9677// #include <nlohmann/detail/input/lexer.hpp>
9678
9679// #include <nlohmann/detail/macro_scope.hpp>
9680
9681// #include <nlohmann/detail/meta/is_sax.hpp>
9682// __ _____ _____ _____
9683// __| | __| | | | JSON for Modern C++
9684// | | |__ | | | | | | version 3.12.0
9685// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9686//
9687// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
9688// SPDX-License-Identifier: MIT
9689
9690
9691
9692#include <cstdint> // size_t
9693#include <utility> // declval
9694#include <string> // string
9695
9696// #include <nlohmann/detail/abi_macros.hpp>
9697
9698// #include <nlohmann/detail/meta/detected.hpp>
9699
9700// #include <nlohmann/detail/meta/type_traits.hpp>
9701
9702
9704namespace detail
9705{
9706
9707template<typename T>
9708using null_function_t = decltype(std::declval<T&>().null());
9709
9710template<typename T>
9712 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9713
9714template<typename T, typename Integer>
9716 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9717
9718template<typename T, typename Unsigned>
9720 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9721
9722template<typename T, typename Float, typename String>
9723using number_float_function_t = decltype(std::declval<T&>().number_float(
9724 std::declval<Float>(), std::declval<const String&>()));
9725
9726template<typename T, typename String>
9728 decltype(std::declval<T&>().string(std::declval<String&>()));
9729
9730template<typename T, typename Binary>
9732 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9733
9734template<typename T>
9736 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9737
9738template<typename T, typename String>
9740 decltype(std::declval<T&>().key(std::declval<String&>()));
9741
9742template<typename T>
9743using end_object_function_t = decltype(std::declval<T&>().end_object());
9744
9745template<typename T>
9747 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9748
9749template<typename T>
9750using end_array_function_t = decltype(std::declval<T&>().end_array());
9751
9752template<typename T, typename Exception>
9753using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9754 std::declval<std::size_t>(), std::declval<const std::string&>(),
9755 std::declval<const Exception&>()));
9756
9757template<typename SAX, typename BasicJsonType>
9759{
9760 private:
9762 "BasicJsonType must be of type basic_json<...>");
9763
9764 using number_integer_t = typename BasicJsonType::number_integer_t;
9765 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9766 using number_float_t = typename BasicJsonType::number_float_t;
9767 using string_t = typename BasicJsonType::string_t;
9768 using binary_t = typename BasicJsonType::binary_t;
9769 using exception_t = typename BasicJsonType::exception;
9770
9771 public:
9772 static constexpr bool value =
9786};
9787
9788template<typename SAX, typename BasicJsonType>
9790{
9791 private:
9793 "BasicJsonType must be of type basic_json<...>");
9794
9795 using number_integer_t = typename BasicJsonType::number_integer_t;
9796 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9797 using number_float_t = typename BasicJsonType::number_float_t;
9798 using string_t = typename BasicJsonType::string_t;
9799 using binary_t = typename BasicJsonType::binary_t;
9800 using exception_t = typename BasicJsonType::exception;
9801
9802 public:
9804 "Missing/invalid function: bool null()");
9806 "Missing/invalid function: bool boolean(bool)");
9808 "Missing/invalid function: bool boolean(bool)");
9809 static_assert(
9811 number_integer_t>::value,
9812 "Missing/invalid function: bool number_integer(number_integer_t)");
9813 static_assert(
9815 number_unsigned_t>::value,
9816 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9817 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9818 number_float_t, string_t>::value,
9819 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9820 static_assert(
9822 "Missing/invalid function: bool string(string_t&)");
9823 static_assert(
9825 "Missing/invalid function: bool binary(binary_t&)");
9827 "Missing/invalid function: bool start_object(std::size_t)");
9829 "Missing/invalid function: bool key(string_t&)");
9831 "Missing/invalid function: bool end_object()");
9833 "Missing/invalid function: bool start_array(std::size_t)");
9835 "Missing/invalid function: bool end_array()");
9836 static_assert(
9838 "Missing/invalid function: bool parse_error(std::size_t, const "
9839 "std::string&, const exception&)");
9840};
9841
9842} // namespace detail
9844
9845// #include <nlohmann/detail/meta/type_traits.hpp>
9846
9847// #include <nlohmann/detail/string_concat.hpp>
9848
9849// #include <nlohmann/detail/value_t.hpp>
9850
9851
9853namespace detail
9854{
9855
9863
9871inline bool little_endianness(int num = 1) noexcept
9872{
9873 return *reinterpret_cast<char*>(&num) == 1;
9874}
9875
9877// binary reader //
9879
9883template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
9885{
9886 using number_integer_t = typename BasicJsonType::number_integer_t;
9887 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9888 using number_float_t = typename BasicJsonType::number_float_t;
9889 using string_t = typename BasicJsonType::string_t;
9890 using binary_t = typename BasicJsonType::binary_t;
9891 using json_sax_t = SAX;
9892 using char_type = typename InputAdapterType::char_type;
9893 using char_int_type = typename char_traits<char_type>::int_type;
9894
9895 public:
9901 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9902 {
9904 }
9905
9906 // make class move-only
9908 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9910 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9911 ~binary_reader() = default;
9912
9922 bool sax_parse(const input_format_t format,
9923 json_sax_t* sax_,
9924 const bool strict = true,
9925 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9926 {
9927 sax = sax_;
9928 bool result = false;
9929
9930 switch (format)
9931 {
9933 result = parse_bson_internal();
9934 break;
9935
9937 result = parse_cbor_internal(true, tag_handler);
9938 break;
9939
9941 result = parse_msgpack_internal();
9942 break;
9943
9946 result = parse_ubjson_internal();
9947 break;
9948
9949 case input_format_t::json: // LCOV_EXCL_LINE
9950 default: // LCOV_EXCL_LINE
9951 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9952 }
9953
9954 // strict mode: next byte must be EOF
9955 if (result && strict)
9956 {
9957 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9958 {
9959 get_ignore_noop();
9960 }
9961 else
9962 {
9963 get();
9964 }
9965
9967 {
9968 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9969 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9970 }
9971 }
9972
9973 return result;
9974 }
9975
9976 private:
9978 // BSON //
9980
9985 bool parse_bson_internal()
9986 {
9987 std::int32_t document_size{};
9988 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9989
9990 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
9991 {
9992 return false;
9993 }
9994
9995 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9996 {
9997 return false;
9998 }
9999
10000 return sax->end_object();
10001 }
10002
10010 bool get_bson_cstr(string_t& result)
10011 {
10012 auto out = std::back_inserter(result);
10013 while (true)
10014 {
10015 get();
10016 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
10017 {
10018 return false;
10019 }
10020 if (current == 0x00)
10021 {
10022 return true;
10023 }
10024 *out++ = static_cast<typename string_t::value_type>(current);
10025 }
10026 }
10027
10039 template<typename NumberType>
10040 bool get_bson_string(const NumberType len, string_t& result)
10041 {
10042 if (JSON_HEDLEY_UNLIKELY(len < 1))
10043 {
10044 auto last_token = get_token_string();
10045 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10046 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10047 }
10048
10049 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10050 }
10051
10061 template<typename NumberType>
10062 bool get_bson_binary(const NumberType len, binary_t& result)
10063 {
10064 if (JSON_HEDLEY_UNLIKELY(len < 0))
10065 {
10066 auto last_token = get_token_string();
10067 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10068 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10069 }
10070
10071 // All BSON binary values have a subtype
10072 std::uint8_t subtype{};
10073 get_number<std::uint8_t>(input_format_t::bson, subtype);
10074 result.set_subtype(subtype);
10075
10076 return get_binary(input_format_t::bson, len, result);
10077 }
10078
10089 bool parse_bson_element_internal(const char_int_type element_type,
10090 const std::size_t element_type_parse_position)
10091 {
10092 switch (element_type)
10093 {
10094 case 0x01: // double
10095 {
10096 double number{};
10097 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10098 }
10099
10100 case 0x02: // string
10101 {
10102 std::int32_t len{};
10103 string_t value;
10104 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10105 }
10106
10107 case 0x03: // object
10108 {
10109 return parse_bson_internal();
10110 }
10111
10112 case 0x04: // array
10113 {
10114 return parse_bson_array();
10115 }
10116
10117 case 0x05: // binary
10118 {
10119 std::int32_t len{};
10120 binary_t value;
10121 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10122 }
10123
10124 case 0x08: // boolean
10125 {
10126 return sax->boolean(get() != 0);
10127 }
10128
10129 case 0x0A: // null
10130 {
10131 return sax->null();
10132 }
10133
10134 case 0x10: // int32
10135 {
10136 std::int32_t value{};
10137 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10138 }
10139
10140 case 0x12: // int64
10141 {
10142 std::int64_t value{};
10143 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10144 }
10145
10146 case 0x11: // uint64
10147 {
10148 std::uint64_t value{};
10149 return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10150 }
10151
10152 default: // anything else is not supported (yet)
10153 {
10154 std::array<char, 3> cr{{}};
10155 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10156 const std::string cr_str{cr.data()};
10157 return sax->parse_error(element_type_parse_position, cr_str,
10158 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10159 }
10160 }
10161 }
10162
10175 bool parse_bson_element_list(const bool is_array)
10176 {
10177 string_t key;
10178
10179 while (auto element_type = get())
10180 {
10181 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10182 {
10183 return false;
10184 }
10185
10186 const std::size_t element_type_parse_position = chars_read;
10187 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10188 {
10189 return false;
10190 }
10191
10192 if (!is_array && !sax->key(key))
10193 {
10194 return false;
10195 }
10196
10197 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10198 {
10199 return false;
10200 }
10201
10202 // get_bson_cstr only appends
10203 key.clear();
10204 }
10205
10206 return true;
10207 }
10208
10213 bool parse_bson_array()
10214 {
10215 std::int32_t document_size{};
10216 get_number<std::int32_t, true>(input_format_t::bson, document_size);
10217
10218 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10219 {
10220 return false;
10221 }
10222
10223 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10224 {
10225 return false;
10226 }
10227
10228 return sax->end_array();
10229 }
10230
10232 // CBOR //
10234
10243 bool parse_cbor_internal(const bool get_char,
10244 const cbor_tag_handler_t tag_handler)
10245 {
10246 switch (get_char ? get() : current)
10247 {
10248 // EOF
10249 case char_traits<char_type>::eof():
10250 return unexpect_eof(input_format_t::cbor, "value");
10251
10252 // Integer 0x00..0x17 (0..23)
10253 case 0x00:
10254 case 0x01:
10255 case 0x02:
10256 case 0x03:
10257 case 0x04:
10258 case 0x05:
10259 case 0x06:
10260 case 0x07:
10261 case 0x08:
10262 case 0x09:
10263 case 0x0A:
10264 case 0x0B:
10265 case 0x0C:
10266 case 0x0D:
10267 case 0x0E:
10268 case 0x0F:
10269 case 0x10:
10270 case 0x11:
10271 case 0x12:
10272 case 0x13:
10273 case 0x14:
10274 case 0x15:
10275 case 0x16:
10276 case 0x17:
10277 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10278
10279 case 0x18: // Unsigned integer (one-byte uint8_t follows)
10280 {
10281 std::uint8_t number{};
10282 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10283 }
10284
10285 case 0x19: // Unsigned integer (two-byte uint16_t follows)
10286 {
10287 std::uint16_t number{};
10288 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10289 }
10290
10291 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10292 {
10293 std::uint32_t number{};
10294 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10295 }
10296
10297 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10298 {
10299 std::uint64_t number{};
10300 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10301 }
10302
10303 // Negative integer -1-0x00..-1-0x17 (-1..-24)
10304 case 0x20:
10305 case 0x21:
10306 case 0x22:
10307 case 0x23:
10308 case 0x24:
10309 case 0x25:
10310 case 0x26:
10311 case 0x27:
10312 case 0x28:
10313 case 0x29:
10314 case 0x2A:
10315 case 0x2B:
10316 case 0x2C:
10317 case 0x2D:
10318 case 0x2E:
10319 case 0x2F:
10320 case 0x30:
10321 case 0x31:
10322 case 0x32:
10323 case 0x33:
10324 case 0x34:
10325 case 0x35:
10326 case 0x36:
10327 case 0x37:
10328 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10329
10330 case 0x38: // Negative integer (one-byte uint8_t follows)
10331 {
10332 std::uint8_t number{};
10333 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10334 }
10335
10336 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10337 {
10338 std::uint16_t number{};
10339 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10340 }
10341
10342 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10343 {
10344 std::uint32_t number{};
10345 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10346 }
10347
10348 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10349 {
10350 std::uint64_t number{};
10351 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10352 - static_cast<number_integer_t>(number));
10353 }
10354
10355 // Binary data (0x00..0x17 bytes follow)
10356 case 0x40:
10357 case 0x41:
10358 case 0x42:
10359 case 0x43:
10360 case 0x44:
10361 case 0x45:
10362 case 0x46:
10363 case 0x47:
10364 case 0x48:
10365 case 0x49:
10366 case 0x4A:
10367 case 0x4B:
10368 case 0x4C:
10369 case 0x4D:
10370 case 0x4E:
10371 case 0x4F:
10372 case 0x50:
10373 case 0x51:
10374 case 0x52:
10375 case 0x53:
10376 case 0x54:
10377 case 0x55:
10378 case 0x56:
10379 case 0x57:
10380 case 0x58: // Binary data (one-byte uint8_t for n follows)
10381 case 0x59: // Binary data (two-byte uint16_t for n follow)
10382 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10383 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10384 case 0x5F: // Binary data (indefinite length)
10385 {
10386 binary_t b;
10387 return get_cbor_binary(b) && sax->binary(b);
10388 }
10389
10390 // UTF-8 string (0x00..0x17 bytes follow)
10391 case 0x60:
10392 case 0x61:
10393 case 0x62:
10394 case 0x63:
10395 case 0x64:
10396 case 0x65:
10397 case 0x66:
10398 case 0x67:
10399 case 0x68:
10400 case 0x69:
10401 case 0x6A:
10402 case 0x6B:
10403 case 0x6C:
10404 case 0x6D:
10405 case 0x6E:
10406 case 0x6F:
10407 case 0x70:
10408 case 0x71:
10409 case 0x72:
10410 case 0x73:
10411 case 0x74:
10412 case 0x75:
10413 case 0x76:
10414 case 0x77:
10415 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10416 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10417 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10418 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10419 case 0x7F: // UTF-8 string (indefinite length)
10420 {
10421 string_t s;
10422 return get_cbor_string(s) && sax->string(s);
10423 }
10424
10425 // array (0x00..0x17 data items follow)
10426 case 0x80:
10427 case 0x81:
10428 case 0x82:
10429 case 0x83:
10430 case 0x84:
10431 case 0x85:
10432 case 0x86:
10433 case 0x87:
10434 case 0x88:
10435 case 0x89:
10436 case 0x8A:
10437 case 0x8B:
10438 case 0x8C:
10439 case 0x8D:
10440 case 0x8E:
10441 case 0x8F:
10442 case 0x90:
10443 case 0x91:
10444 case 0x92:
10445 case 0x93:
10446 case 0x94:
10447 case 0x95:
10448 case 0x96:
10449 case 0x97:
10450 return get_cbor_array(
10451 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10452
10453 case 0x98: // array (one-byte uint8_t for n follows)
10454 {
10455 std::uint8_t len{};
10456 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10457 }
10458
10459 case 0x99: // array (two-byte uint16_t for n follow)
10460 {
10461 std::uint16_t len{};
10462 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10463 }
10464
10465 case 0x9A: // array (four-byte uint32_t for n follow)
10466 {
10467 std::uint32_t len{};
10468 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10469 }
10470
10471 case 0x9B: // array (eight-byte uint64_t for n follow)
10472 {
10473 std::uint64_t len{};
10474 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10475 }
10476
10477 case 0x9F: // array (indefinite length)
10478 return get_cbor_array(detail::unknown_size(), tag_handler);
10479
10480 // map (0x00..0x17 pairs of data items follow)
10481 case 0xA0:
10482 case 0xA1:
10483 case 0xA2:
10484 case 0xA3:
10485 case 0xA4:
10486 case 0xA5:
10487 case 0xA6:
10488 case 0xA7:
10489 case 0xA8:
10490 case 0xA9:
10491 case 0xAA:
10492 case 0xAB:
10493 case 0xAC:
10494 case 0xAD:
10495 case 0xAE:
10496 case 0xAF:
10497 case 0xB0:
10498 case 0xB1:
10499 case 0xB2:
10500 case 0xB3:
10501 case 0xB4:
10502 case 0xB5:
10503 case 0xB6:
10504 case 0xB7:
10505 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10506
10507 case 0xB8: // map (one-byte uint8_t for n follows)
10508 {
10509 std::uint8_t len{};
10510 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10511 }
10512
10513 case 0xB9: // map (two-byte uint16_t for n follow)
10514 {
10515 std::uint16_t len{};
10516 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10517 }
10518
10519 case 0xBA: // map (four-byte uint32_t for n follow)
10520 {
10521 std::uint32_t len{};
10522 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10523 }
10524
10525 case 0xBB: // map (eight-byte uint64_t for n follow)
10526 {
10527 std::uint64_t len{};
10528 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10529 }
10530
10531 case 0xBF: // map (indefinite length)
10532 return get_cbor_object(detail::unknown_size(), tag_handler);
10533
10534 case 0xC6: // tagged item
10535 case 0xC7:
10536 case 0xC8:
10537 case 0xC9:
10538 case 0xCA:
10539 case 0xCB:
10540 case 0xCC:
10541 case 0xCD:
10542 case 0xCE:
10543 case 0xCF:
10544 case 0xD0:
10545 case 0xD1:
10546 case 0xD2:
10547 case 0xD3:
10548 case 0xD4:
10549 case 0xD8: // tagged item (1 byte follows)
10550 case 0xD9: // tagged item (2 bytes follow)
10551 case 0xDA: // tagged item (4 bytes follow)
10552 case 0xDB: // tagged item (8 bytes follow)
10553 {
10554 switch (tag_handler)
10555 {
10556 case cbor_tag_handler_t::error:
10557 {
10558 auto last_token = get_token_string();
10559 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10560 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10561 }
10562
10563 case cbor_tag_handler_t::ignore:
10564 {
10565 // ignore binary subtype
10566 switch (current)
10567 {
10568 case 0xD8:
10569 {
10570 std::uint8_t subtype_to_ignore{};
10571 get_number(input_format_t::cbor, subtype_to_ignore);
10572 break;
10573 }
10574 case 0xD9:
10575 {
10576 std::uint16_t subtype_to_ignore{};
10577 get_number(input_format_t::cbor, subtype_to_ignore);
10578 break;
10579 }
10580 case 0xDA:
10581 {
10582 std::uint32_t subtype_to_ignore{};
10583 get_number(input_format_t::cbor, subtype_to_ignore);
10584 break;
10585 }
10586 case 0xDB:
10587 {
10588 std::uint64_t subtype_to_ignore{};
10589 get_number(input_format_t::cbor, subtype_to_ignore);
10590 break;
10591 }
10592 default:
10593 break;
10594 }
10595 return parse_cbor_internal(true, tag_handler);
10596 }
10597
10598 case cbor_tag_handler_t::store:
10599 {
10600 binary_t b;
10601 // use binary subtype and store in a binary container
10602 switch (current)
10603 {
10604 case 0xD8:
10605 {
10606 std::uint8_t subtype{};
10607 get_number(input_format_t::cbor, subtype);
10609 break;
10610 }
10611 case 0xD9:
10612 {
10613 std::uint16_t subtype{};
10614 get_number(input_format_t::cbor, subtype);
10616 break;
10617 }
10618 case 0xDA:
10619 {
10620 std::uint32_t subtype{};
10621 get_number(input_format_t::cbor, subtype);
10623 break;
10624 }
10625 case 0xDB:
10626 {
10627 std::uint64_t subtype{};
10628 get_number(input_format_t::cbor, subtype);
10630 break;
10631 }
10632 default:
10633 return parse_cbor_internal(true, tag_handler);
10634 }
10635 get();
10636 return get_cbor_binary(b) && sax->binary(b);
10637 }
10638
10639 default: // LCOV_EXCL_LINE
10640 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10641 return false; // LCOV_EXCL_LINE
10642 }
10643 }
10644
10645 case 0xF4: // false
10646 return sax->boolean(false);
10647
10648 case 0xF5: // true
10649 return sax->boolean(true);
10650
10651 case 0xF6: // null
10652 return sax->null();
10653
10654 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10655 {
10656 const auto byte1_raw = get();
10657 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10658 {
10659 return false;
10660 }
10661 const auto byte2_raw = get();
10662 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10663 {
10664 return false;
10665 }
10666
10667 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10668 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10669
10670 // Code from RFC 7049, Appendix D, Figure 3:
10671 // As half-precision floating-point numbers were only added
10672 // to IEEE 754 in 2008, today's programming platforms often
10673 // still only have limited support for them. It is very
10674 // easy to include at least decoding support for them even
10675 // without such support. An example of a small decoder for
10676 // half-precision floating-point numbers in the C language
10677 // is shown in Fig. 3.
10678 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10679 const double val = [&half]
10680 {
10681 const int exp = (half >> 10u) & 0x1Fu;
10682 const unsigned int mant = half & 0x3FFu;
10683 JSON_ASSERT(0 <= exp&& exp <= 32);
10684 JSON_ASSERT(mant <= 1024);
10685 switch (exp)
10686 {
10687 case 0:
10688 return std::ldexp(mant, -24);
10689 case 31:
10690 return (mant == 0)
10691 ? std::numeric_limits<double>::infinity()
10692 : std::numeric_limits<double>::quiet_NaN();
10693 default:
10694 return std::ldexp(mant + 1024, exp - 25);
10695 }
10696 }();
10697 return sax->number_float((half & 0x8000u) != 0
10698 ? static_cast<number_float_t>(-val)
10699 : static_cast<number_float_t>(val), "");
10700 }
10701
10702 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10703 {
10704 float number{};
10705 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10706 }
10707
10708 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10709 {
10710 double number{};
10711 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10712 }
10713
10714 default: // anything else (0xFF is handled inside the other types)
10715 {
10716 auto last_token = get_token_string();
10717 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10718 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10719 }
10720 }
10721 }
10722
10734 bool get_cbor_string(string_t& result)
10735 {
10736 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10737 {
10738 return false;
10739 }
10740
10741 switch (current)
10742 {
10743 // UTF-8 string (0x00..0x17 bytes follow)
10744 case 0x60:
10745 case 0x61:
10746 case 0x62:
10747 case 0x63:
10748 case 0x64:
10749 case 0x65:
10750 case 0x66:
10751 case 0x67:
10752 case 0x68:
10753 case 0x69:
10754 case 0x6A:
10755 case 0x6B:
10756 case 0x6C:
10757 case 0x6D:
10758 case 0x6E:
10759 case 0x6F:
10760 case 0x70:
10761 case 0x71:
10762 case 0x72:
10763 case 0x73:
10764 case 0x74:
10765 case 0x75:
10766 case 0x76:
10767 case 0x77:
10768 {
10769 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10770 }
10771
10772 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10773 {
10774 std::uint8_t len{};
10775 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10776 }
10777
10778 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10779 {
10780 std::uint16_t len{};
10781 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10782 }
10783
10784 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10785 {
10786 std::uint32_t len{};
10787 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10788 }
10789
10790 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10791 {
10792 std::uint64_t len{};
10793 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10794 }
10795
10796 case 0x7F: // UTF-8 string (indefinite length)
10797 {
10798 while (get() != 0xFF)
10799 {
10800 string_t chunk;
10801 if (!get_cbor_string(chunk))
10802 {
10803 return false;
10804 }
10805 result.append(chunk);
10806 }
10807 return true;
10808 }
10809
10810 default:
10811 {
10812 auto last_token = get_token_string();
10813 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10814 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10815 }
10816 }
10817 }
10818
10830 bool get_cbor_binary(binary_t& result)
10831 {
10832 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10833 {
10834 return false;
10835 }
10836
10837 switch (current)
10838 {
10839 // Binary data (0x00..0x17 bytes follow)
10840 case 0x40:
10841 case 0x41:
10842 case 0x42:
10843 case 0x43:
10844 case 0x44:
10845 case 0x45:
10846 case 0x46:
10847 case 0x47:
10848 case 0x48:
10849 case 0x49:
10850 case 0x4A:
10851 case 0x4B:
10852 case 0x4C:
10853 case 0x4D:
10854 case 0x4E:
10855 case 0x4F:
10856 case 0x50:
10857 case 0x51:
10858 case 0x52:
10859 case 0x53:
10860 case 0x54:
10861 case 0x55:
10862 case 0x56:
10863 case 0x57:
10864 {
10865 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10866 }
10867
10868 case 0x58: // Binary data (one-byte uint8_t for n follows)
10869 {
10870 std::uint8_t len{};
10871 return get_number(input_format_t::cbor, len) &&
10872 get_binary(input_format_t::cbor, len, result);
10873 }
10874
10875 case 0x59: // Binary data (two-byte uint16_t for n follow)
10876 {
10877 std::uint16_t len{};
10878 return get_number(input_format_t::cbor, len) &&
10879 get_binary(input_format_t::cbor, len, result);
10880 }
10881
10882 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10883 {
10884 std::uint32_t len{};
10885 return get_number(input_format_t::cbor, len) &&
10886 get_binary(input_format_t::cbor, len, result);
10887 }
10888
10889 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10890 {
10891 std::uint64_t len{};
10892 return get_number(input_format_t::cbor, len) &&
10893 get_binary(input_format_t::cbor, len, result);
10894 }
10895
10896 case 0x5F: // Binary data (indefinite length)
10897 {
10898 while (get() != 0xFF)
10899 {
10900 binary_t chunk;
10901 if (!get_cbor_binary(chunk))
10902 {
10903 return false;
10904 }
10905 result.insert(result.end(), chunk.begin(), chunk.end());
10906 }
10907 return true;
10908 }
10909
10910 default:
10911 {
10912 auto last_token = get_token_string();
10913 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10914 exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
10915 }
10916 }
10917 }
10918
10925 bool get_cbor_array(const std::size_t len,
10926 const cbor_tag_handler_t tag_handler)
10927 {
10928 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10929 {
10930 return false;
10931 }
10932
10933 if (len != detail::unknown_size())
10934 {
10935 for (std::size_t i = 0; i < len; ++i)
10936 {
10937 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10938 {
10939 return false;
10940 }
10941 }
10942 }
10943 else
10944 {
10945 while (get() != 0xFF)
10946 {
10947 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10948 {
10949 return false;
10950 }
10951 }
10952 }
10953
10954 return sax->end_array();
10955 }
10956
10963 bool get_cbor_object(const std::size_t len,
10964 const cbor_tag_handler_t tag_handler)
10965 {
10966 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10967 {
10968 return false;
10969 }
10970
10971 if (len != 0)
10972 {
10973 string_t key;
10974 if (len != detail::unknown_size())
10975 {
10976 for (std::size_t i = 0; i < len; ++i)
10977 {
10978 get();
10979 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10980 {
10981 return false;
10982 }
10983
10984 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10985 {
10986 return false;
10987 }
10988 key.clear();
10989 }
10990 }
10991 else
10992 {
10993 while (get() != 0xFF)
10994 {
10995 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10996 {
10997 return false;
10998 }
10999
11000 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
11001 {
11002 return false;
11003 }
11004 key.clear();
11005 }
11006 }
11007 }
11008
11009 return sax->end_object();
11010 }
11011
11013 // MsgPack //
11015
11019 bool parse_msgpack_internal()
11020 {
11021 switch (get())
11022 {
11023 // EOF
11024 case char_traits<char_type>::eof():
11025 return unexpect_eof(input_format_t::msgpack, "value");
11026
11027 // positive fixint
11028 case 0x00:
11029 case 0x01:
11030 case 0x02:
11031 case 0x03:
11032 case 0x04:
11033 case 0x05:
11034 case 0x06:
11035 case 0x07:
11036 case 0x08:
11037 case 0x09:
11038 case 0x0A:
11039 case 0x0B:
11040 case 0x0C:
11041 case 0x0D:
11042 case 0x0E:
11043 case 0x0F:
11044 case 0x10:
11045 case 0x11:
11046 case 0x12:
11047 case 0x13:
11048 case 0x14:
11049 case 0x15:
11050 case 0x16:
11051 case 0x17:
11052 case 0x18:
11053 case 0x19:
11054 case 0x1A:
11055 case 0x1B:
11056 case 0x1C:
11057 case 0x1D:
11058 case 0x1E:
11059 case 0x1F:
11060 case 0x20:
11061 case 0x21:
11062 case 0x22:
11063 case 0x23:
11064 case 0x24:
11065 case 0x25:
11066 case 0x26:
11067 case 0x27:
11068 case 0x28:
11069 case 0x29:
11070 case 0x2A:
11071 case 0x2B:
11072 case 0x2C:
11073 case 0x2D:
11074 case 0x2E:
11075 case 0x2F:
11076 case 0x30:
11077 case 0x31:
11078 case 0x32:
11079 case 0x33:
11080 case 0x34:
11081 case 0x35:
11082 case 0x36:
11083 case 0x37:
11084 case 0x38:
11085 case 0x39:
11086 case 0x3A:
11087 case 0x3B:
11088 case 0x3C:
11089 case 0x3D:
11090 case 0x3E:
11091 case 0x3F:
11092 case 0x40:
11093 case 0x41:
11094 case 0x42:
11095 case 0x43:
11096 case 0x44:
11097 case 0x45:
11098 case 0x46:
11099 case 0x47:
11100 case 0x48:
11101 case 0x49:
11102 case 0x4A:
11103 case 0x4B:
11104 case 0x4C:
11105 case 0x4D:
11106 case 0x4E:
11107 case 0x4F:
11108 case 0x50:
11109 case 0x51:
11110 case 0x52:
11111 case 0x53:
11112 case 0x54:
11113 case 0x55:
11114 case 0x56:
11115 case 0x57:
11116 case 0x58:
11117 case 0x59:
11118 case 0x5A:
11119 case 0x5B:
11120 case 0x5C:
11121 case 0x5D:
11122 case 0x5E:
11123 case 0x5F:
11124 case 0x60:
11125 case 0x61:
11126 case 0x62:
11127 case 0x63:
11128 case 0x64:
11129 case 0x65:
11130 case 0x66:
11131 case 0x67:
11132 case 0x68:
11133 case 0x69:
11134 case 0x6A:
11135 case 0x6B:
11136 case 0x6C:
11137 case 0x6D:
11138 case 0x6E:
11139 case 0x6F:
11140 case 0x70:
11141 case 0x71:
11142 case 0x72:
11143 case 0x73:
11144 case 0x74:
11145 case 0x75:
11146 case 0x76:
11147 case 0x77:
11148 case 0x78:
11149 case 0x79:
11150 case 0x7A:
11151 case 0x7B:
11152 case 0x7C:
11153 case 0x7D:
11154 case 0x7E:
11155 case 0x7F:
11156 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11157
11158 // fixmap
11159 case 0x80:
11160 case 0x81:
11161 case 0x82:
11162 case 0x83:
11163 case 0x84:
11164 case 0x85:
11165 case 0x86:
11166 case 0x87:
11167 case 0x88:
11168 case 0x89:
11169 case 0x8A:
11170 case 0x8B:
11171 case 0x8C:
11172 case 0x8D:
11173 case 0x8E:
11174 case 0x8F:
11175 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11176
11177 // fixarray
11178 case 0x90:
11179 case 0x91:
11180 case 0x92:
11181 case 0x93:
11182 case 0x94:
11183 case 0x95:
11184 case 0x96:
11185 case 0x97:
11186 case 0x98:
11187 case 0x99:
11188 case 0x9A:
11189 case 0x9B:
11190 case 0x9C:
11191 case 0x9D:
11192 case 0x9E:
11193 case 0x9F:
11194 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11195
11196 // fixstr
11197 case 0xA0:
11198 case 0xA1:
11199 case 0xA2:
11200 case 0xA3:
11201 case 0xA4:
11202 case 0xA5:
11203 case 0xA6:
11204 case 0xA7:
11205 case 0xA8:
11206 case 0xA9:
11207 case 0xAA:
11208 case 0xAB:
11209 case 0xAC:
11210 case 0xAD:
11211 case 0xAE:
11212 case 0xAF:
11213 case 0xB0:
11214 case 0xB1:
11215 case 0xB2:
11216 case 0xB3:
11217 case 0xB4:
11218 case 0xB5:
11219 case 0xB6:
11220 case 0xB7:
11221 case 0xB8:
11222 case 0xB9:
11223 case 0xBA:
11224 case 0xBB:
11225 case 0xBC:
11226 case 0xBD:
11227 case 0xBE:
11228 case 0xBF:
11229 case 0xD9: // str 8
11230 case 0xDA: // str 16
11231 case 0xDB: // str 32
11232 {
11233 string_t s;
11234 return get_msgpack_string(s) && sax->string(s);
11235 }
11236
11237 case 0xC0: // nil
11238 return sax->null();
11239
11240 case 0xC2: // false
11241 return sax->boolean(false);
11242
11243 case 0xC3: // true
11244 return sax->boolean(true);
11245
11246 case 0xC4: // bin 8
11247 case 0xC5: // bin 16
11248 case 0xC6: // bin 32
11249 case 0xC7: // ext 8
11250 case 0xC8: // ext 16
11251 case 0xC9: // ext 32
11252 case 0xD4: // fixext 1
11253 case 0xD5: // fixext 2
11254 case 0xD6: // fixext 4
11255 case 0xD7: // fixext 8
11256 case 0xD8: // fixext 16
11257 {
11258 binary_t b;
11259 return get_msgpack_binary(b) && sax->binary(b);
11260 }
11261
11262 case 0xCA: // float 32
11263 {
11264 float number{};
11265 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11266 }
11267
11268 case 0xCB: // float 64
11269 {
11270 double number{};
11271 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11272 }
11273
11274 case 0xCC: // uint 8
11275 {
11276 std::uint8_t number{};
11277 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11278 }
11279
11280 case 0xCD: // uint 16
11281 {
11282 std::uint16_t number{};
11283 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11284 }
11285
11286 case 0xCE: // uint 32
11287 {
11288 std::uint32_t number{};
11289 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11290 }
11291
11292 case 0xCF: // uint 64
11293 {
11294 std::uint64_t number{};
11295 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11296 }
11297
11298 case 0xD0: // int 8
11299 {
11300 std::int8_t number{};
11301 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11302 }
11303
11304 case 0xD1: // int 16
11305 {
11306 std::int16_t number{};
11307 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11308 }
11309
11310 case 0xD2: // int 32
11311 {
11312 std::int32_t number{};
11313 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11314 }
11315
11316 case 0xD3: // int 64
11317 {
11318 std::int64_t number{};
11319 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11320 }
11321
11322 case 0xDC: // array 16
11323 {
11324 std::uint16_t len{};
11325 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11326 }
11327
11328 case 0xDD: // array 32
11329 {
11330 std::uint32_t len{};
11331 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11332 }
11333
11334 case 0xDE: // map 16
11335 {
11336 std::uint16_t len{};
11337 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11338 }
11339
11340 case 0xDF: // map 32
11341 {
11342 std::uint32_t len{};
11343 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11344 }
11345
11346 // negative fixint
11347 case 0xE0:
11348 case 0xE1:
11349 case 0xE2:
11350 case 0xE3:
11351 case 0xE4:
11352 case 0xE5:
11353 case 0xE6:
11354 case 0xE7:
11355 case 0xE8:
11356 case 0xE9:
11357 case 0xEA:
11358 case 0xEB:
11359 case 0xEC:
11360 case 0xED:
11361 case 0xEE:
11362 case 0xEF:
11363 case 0xF0:
11364 case 0xF1:
11365 case 0xF2:
11366 case 0xF3:
11367 case 0xF4:
11368 case 0xF5:
11369 case 0xF6:
11370 case 0xF7:
11371 case 0xF8:
11372 case 0xF9:
11373 case 0xFA:
11374 case 0xFB:
11375 case 0xFC:
11376 case 0xFD:
11377 case 0xFE:
11378 case 0xFF:
11379 return sax->number_integer(static_cast<std::int8_t>(current));
11380
11381 default: // anything else
11382 {
11383 auto last_token = get_token_string();
11384 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11385 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11386 }
11387 }
11388 }
11389
11400 bool get_msgpack_string(string_t& result)
11401 {
11402 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11403 {
11404 return false;
11405 }
11406
11407 switch (current)
11408 {
11409 // fixstr
11410 case 0xA0:
11411 case 0xA1:
11412 case 0xA2:
11413 case 0xA3:
11414 case 0xA4:
11415 case 0xA5:
11416 case 0xA6:
11417 case 0xA7:
11418 case 0xA8:
11419 case 0xA9:
11420 case 0xAA:
11421 case 0xAB:
11422 case 0xAC:
11423 case 0xAD:
11424 case 0xAE:
11425 case 0xAF:
11426 case 0xB0:
11427 case 0xB1:
11428 case 0xB2:
11429 case 0xB3:
11430 case 0xB4:
11431 case 0xB5:
11432 case 0xB6:
11433 case 0xB7:
11434 case 0xB8:
11435 case 0xB9:
11436 case 0xBA:
11437 case 0xBB:
11438 case 0xBC:
11439 case 0xBD:
11440 case 0xBE:
11441 case 0xBF:
11442 {
11443 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11444 }
11445
11446 case 0xD9: // str 8
11447 {
11448 std::uint8_t len{};
11449 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11450 }
11451
11452 case 0xDA: // str 16
11453 {
11454 std::uint16_t len{};
11455 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11456 }
11457
11458 case 0xDB: // str 32
11459 {
11460 std::uint32_t len{};
11461 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11462 }
11463
11464 default:
11465 {
11466 auto last_token = get_token_string();
11467 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11468 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11469 }
11470 }
11471 }
11472
11483 bool get_msgpack_binary(binary_t& result)
11484 {
11485 // helper function to set the subtype
11486 auto assign_and_return_true = [&result](std::int8_t subtype)
11487 {
11488 result.set_subtype(static_cast<std::uint8_t>(subtype));
11489 return true;
11490 };
11491
11492 switch (current)
11493 {
11494 case 0xC4: // bin 8
11495 {
11496 std::uint8_t len{};
11497 return get_number(input_format_t::msgpack, len) &&
11498 get_binary(input_format_t::msgpack, len, result);
11499 }
11500
11501 case 0xC5: // bin 16
11502 {
11503 std::uint16_t len{};
11504 return get_number(input_format_t::msgpack, len) &&
11505 get_binary(input_format_t::msgpack, len, result);
11506 }
11507
11508 case 0xC6: // bin 32
11509 {
11510 std::uint32_t len{};
11511 return get_number(input_format_t::msgpack, len) &&
11512 get_binary(input_format_t::msgpack, len, result);
11513 }
11514
11515 case 0xC7: // ext 8
11516 {
11517 std::uint8_t len{};
11518 std::int8_t subtype{};
11519 return get_number(input_format_t::msgpack, len) &&
11520 get_number(input_format_t::msgpack, subtype) &&
11521 get_binary(input_format_t::msgpack, len, result) &&
11522 assign_and_return_true(subtype);
11523 }
11524
11525 case 0xC8: // ext 16
11526 {
11527 std::uint16_t len{};
11528 std::int8_t subtype{};
11529 return get_number(input_format_t::msgpack, len) &&
11530 get_number(input_format_t::msgpack, subtype) &&
11531 get_binary(input_format_t::msgpack, len, result) &&
11532 assign_and_return_true(subtype);
11533 }
11534
11535 case 0xC9: // ext 32
11536 {
11537 std::uint32_t len{};
11538 std::int8_t subtype{};
11539 return get_number(input_format_t::msgpack, len) &&
11540 get_number(input_format_t::msgpack, subtype) &&
11541 get_binary(input_format_t::msgpack, len, result) &&
11542 assign_and_return_true(subtype);
11543 }
11544
11545 case 0xD4: // fixext 1
11546 {
11547 std::int8_t subtype{};
11548 return get_number(input_format_t::msgpack, subtype) &&
11549 get_binary(input_format_t::msgpack, 1, result) &&
11550 assign_and_return_true(subtype);
11551 }
11552
11553 case 0xD5: // fixext 2
11554 {
11555 std::int8_t subtype{};
11556 return get_number(input_format_t::msgpack, subtype) &&
11557 get_binary(input_format_t::msgpack, 2, result) &&
11558 assign_and_return_true(subtype);
11559 }
11560
11561 case 0xD6: // fixext 4
11562 {
11563 std::int8_t subtype{};
11564 return get_number(input_format_t::msgpack, subtype) &&
11565 get_binary(input_format_t::msgpack, 4, result) &&
11566 assign_and_return_true(subtype);
11567 }
11568
11569 case 0xD7: // fixext 8
11570 {
11571 std::int8_t subtype{};
11572 return get_number(input_format_t::msgpack, subtype) &&
11573 get_binary(input_format_t::msgpack, 8, result) &&
11574 assign_and_return_true(subtype);
11575 }
11576
11577 case 0xD8: // fixext 16
11578 {
11579 std::int8_t subtype{};
11580 return get_number(input_format_t::msgpack, subtype) &&
11581 get_binary(input_format_t::msgpack, 16, result) &&
11582 assign_and_return_true(subtype);
11583 }
11584
11585 default: // LCOV_EXCL_LINE
11586 return false; // LCOV_EXCL_LINE
11587 }
11588 }
11589
11594 bool get_msgpack_array(const std::size_t len)
11595 {
11596 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11597 {
11598 return false;
11599 }
11600
11601 for (std::size_t i = 0; i < len; ++i)
11602 {
11603 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11604 {
11605 return false;
11606 }
11607 }
11608
11609 return sax->end_array();
11610 }
11611
11616 bool get_msgpack_object(const std::size_t len)
11617 {
11618 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11619 {
11620 return false;
11621 }
11622
11623 string_t key;
11624 for (std::size_t i = 0; i < len; ++i)
11625 {
11626 get();
11627 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11628 {
11629 return false;
11630 }
11631
11632 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11633 {
11634 return false;
11635 }
11636 key.clear();
11637 }
11638
11639 return sax->end_object();
11640 }
11641
11643 // UBJSON //
11645
11653 bool parse_ubjson_internal(const bool get_char = true)
11654 {
11655 return get_ubjson_value(get_char ? get_ignore_noop() : current);
11656 }
11657
11672 bool get_ubjson_string(string_t& result, const bool get_char = true)
11673 {
11674 if (get_char)
11675 {
11676 get(); // TODO(niels): may we ignore N here?
11677 }
11678
11679 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11680 {
11681 return false;
11682 }
11683
11684 switch (current)
11685 {
11686 case 'U':
11687 {
11688 std::uint8_t len{};
11689 return get_number(input_format, len) && get_string(input_format, len, result);
11690 }
11691
11692 case 'i':
11693 {
11694 std::int8_t len{};
11695 return get_number(input_format, len) && get_string(input_format, len, result);
11696 }
11697
11698 case 'I':
11699 {
11700 std::int16_t len{};
11701 return get_number(input_format, len) && get_string(input_format, len, result);
11702 }
11703
11704 case 'l':
11705 {
11706 std::int32_t len{};
11707 return get_number(input_format, len) && get_string(input_format, len, result);
11708 }
11709
11710 case 'L':
11711 {
11712 std::int64_t len{};
11713 return get_number(input_format, len) && get_string(input_format, len, result);
11714 }
11715
11716 case 'u':
11717 {
11718 if (input_format != input_format_t::bjdata)
11719 {
11720 break;
11721 }
11722 std::uint16_t len{};
11723 return get_number(input_format, len) && get_string(input_format, len, result);
11724 }
11725
11726 case 'm':
11727 {
11728 if (input_format != input_format_t::bjdata)
11729 {
11730 break;
11731 }
11732 std::uint32_t len{};
11733 return get_number(input_format, len) && get_string(input_format, len, result);
11734 }
11735
11736 case 'M':
11737 {
11738 if (input_format != input_format_t::bjdata)
11739 {
11740 break;
11741 }
11742 std::uint64_t len{};
11743 return get_number(input_format, len) && get_string(input_format, len, result);
11744 }
11745
11746 default:
11747 break;
11748 }
11749 auto last_token = get_token_string();
11750 std::string message;
11751
11752 if (input_format != input_format_t::bjdata)
11753 {
11754 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11755 }
11756 else
11757 {
11758 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11759 }
11760 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11761 }
11762
11767 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11768 {
11769 std::pair<std::size_t, char_int_type> size_and_type;
11770 size_t dimlen = 0;
11771 bool no_ndarray = true;
11772
11773 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11774 {
11775 return false;
11776 }
11777
11778 if (size_and_type.first != npos)
11779 {
11780 if (size_and_type.second != 0)
11781 {
11782 if (size_and_type.second != 'N')
11783 {
11784 for (std::size_t i = 0; i < size_and_type.first; ++i)
11785 {
11786 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11787 {
11788 return false;
11789 }
11790 dim.push_back(dimlen);
11791 }
11792 }
11793 }
11794 else
11795 {
11796 for (std::size_t i = 0; i < size_and_type.first; ++i)
11797 {
11798 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11799 {
11800 return false;
11801 }
11802 dim.push_back(dimlen);
11803 }
11804 }
11805 }
11806 else
11807 {
11808 while (current != ']')
11809 {
11810 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11811 {
11812 return false;
11813 }
11814 dim.push_back(dimlen);
11815 get_ignore_noop();
11816 }
11817 }
11818 return true;
11819 }
11820
11832 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11833 {
11834 if (prefix == 0)
11835 {
11836 prefix = get_ignore_noop();
11837 }
11838
11839 switch (prefix)
11840 {
11841 case 'U':
11842 {
11843 std::uint8_t number{};
11844 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11845 {
11846 return false;
11847 }
11848 result = static_cast<std::size_t>(number);
11849 return true;
11850 }
11851
11852 case 'i':
11853 {
11854 std::int8_t number{};
11855 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11856 {
11857 return false;
11858 }
11859 if (number < 0)
11860 {
11861 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11862 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11863 }
11864 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11865 return true;
11866 }
11867
11868 case 'I':
11869 {
11870 std::int16_t number{};
11871 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11872 {
11873 return false;
11874 }
11875 if (number < 0)
11876 {
11877 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11878 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11879 }
11880 result = static_cast<std::size_t>(number);
11881 return true;
11882 }
11883
11884 case 'l':
11885 {
11886 std::int32_t number{};
11887 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11888 {
11889 return false;
11890 }
11891 if (number < 0)
11892 {
11893 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11894 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11895 }
11896 result = static_cast<std::size_t>(number);
11897 return true;
11898 }
11899
11900 case 'L':
11901 {
11902 std::int64_t number{};
11903 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11904 {
11905 return false;
11906 }
11907 if (number < 0)
11908 {
11909 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11910 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11911 }
11912 if (!value_in_range_of<std::size_t>(number))
11913 {
11914 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11915 exception_message(input_format, "integer value overflow", "size"), nullptr));
11916 }
11917 result = static_cast<std::size_t>(number);
11918 return true;
11919 }
11920
11921 case 'u':
11922 {
11923 if (input_format != input_format_t::bjdata)
11924 {
11925 break;
11926 }
11927 std::uint16_t number{};
11928 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11929 {
11930 return false;
11931 }
11932 result = static_cast<std::size_t>(number);
11933 return true;
11934 }
11935
11936 case 'm':
11937 {
11938 if (input_format != input_format_t::bjdata)
11939 {
11940 break;
11941 }
11942 std::uint32_t number{};
11943 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11944 {
11945 return false;
11946 }
11947 result = conditional_static_cast<std::size_t>(number);
11948 return true;
11949 }
11950
11951 case 'M':
11952 {
11953 if (input_format != input_format_t::bjdata)
11954 {
11955 break;
11956 }
11957 std::uint64_t number{};
11958 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11959 {
11960 return false;
11961 }
11962 if (!value_in_range_of<std::size_t>(number))
11963 {
11964 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11965 exception_message(input_format, "integer value overflow", "size"), nullptr));
11966 }
11968 return true;
11969 }
11970
11971 case '[':
11972 {
11973 if (input_format != input_format_t::bjdata)
11974 {
11975 break;
11976 }
11977 if (is_ndarray) // ndarray dimensional vector can only contain integers and cannot embed another array
11978 {
11979 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
11980 }
11981 std::vector<size_t> dim;
11982 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11983 {
11984 return false;
11985 }
11986 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11987 {
11988 result = dim.at(dim.size() - 1);
11989 return true;
11990 }
11991 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11992 {
11993 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11994 {
11995 if ( i == 0 )
11996 {
11997 result = 0;
11998 return true;
11999 }
12000 }
12001
12002 string_t key = "_ArraySize_";
12003 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
12004 {
12005 return false;
12006 }
12007 result = 1;
12008 for (auto i : dim)
12009 {
12010 // Pre-multiplication overflow check: if i > 0 and result > SIZE_MAX/i, then result*i would overflow.
12011 // This check must happen before multiplication since overflow detection after the fact is unreliable
12012 // as modular arithmetic can produce any value, not just 0 or SIZE_MAX.
12013 if (JSON_HEDLEY_UNLIKELY(i > 0 && result > (std::numeric_limits<std::size_t>::max)() / i))
12014 {
12015 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
12016 }
12017 result *= i;
12018 // Additional post-multiplication check to catch any edge cases the pre-check might miss
12019 if (result == 0 || result == npos)
12020 {
12021 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
12022 }
12023 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
12024 {
12025 return false;
12026 }
12027 }
12028 is_ndarray = true;
12029 return sax->end_array();
12030 }
12031 result = 0;
12032 return true;
12033 }
12034
12035 default:
12036 break;
12037 }
12038 auto last_token = get_token_string();
12039 std::string message;
12040
12041 if (input_format != input_format_t::bjdata)
12042 {
12043 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
12044 }
12045 else
12046 {
12047 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12048 }
12049 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12050 }
12051
12063 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12064 {
12065 result.first = npos; // size
12066 result.second = 0; // type
12067 bool is_ndarray = false;
12068
12069 get_ignore_noop();
12070
12071 if (current == '$')
12072 {
12073 result.second = get(); // must not ignore 'N', because 'N' maybe the type
12074 if (input_format == input_format_t::bjdata
12075 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12076 {
12077 auto last_token = get_token_string();
12078 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12079 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12080 }
12081
12082 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12083 {
12084 return false;
12085 }
12086
12087 get_ignore_noop();
12088 if (JSON_HEDLEY_UNLIKELY(current != '#'))
12089 {
12090 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12091 {
12092 return false;
12093 }
12094 auto last_token = get_token_string();
12095 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12096 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12097 }
12098
12099 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12100 if (input_format == input_format_t::bjdata && is_ndarray)
12101 {
12102 if (inside_ndarray)
12103 {
12104 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12105 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12106 }
12107 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12108 }
12109 return is_error;
12110 }
12111
12112 if (current == '#')
12113 {
12114 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12115 if (input_format == input_format_t::bjdata && is_ndarray)
12116 {
12117 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12118 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12119 }
12120 return is_error;
12121 }
12122
12123 return true;
12124 }
12125
12130 bool get_ubjson_value(const char_int_type prefix)
12131 {
12132 switch (prefix)
12133 {
12134 case char_traits<char_type>::eof(): // EOF
12135 return unexpect_eof(input_format, "value");
12136
12137 case 'T': // true
12138 return sax->boolean(true);
12139 case 'F': // false
12140 return sax->boolean(false);
12141
12142 case 'Z': // null
12143 return sax->null();
12144
12145 case 'B': // byte
12146 {
12147 if (input_format != input_format_t::bjdata)
12148 {
12149 break;
12150 }
12151 std::uint8_t number{};
12152 return get_number(input_format, number) && sax->number_unsigned(number);
12153 }
12154
12155 case 'U':
12156 {
12157 std::uint8_t number{};
12158 return get_number(input_format, number) && sax->number_unsigned(number);
12159 }
12160
12161 case 'i':
12162 {
12163 std::int8_t number{};
12164 return get_number(input_format, number) && sax->number_integer(number);
12165 }
12166
12167 case 'I':
12168 {
12169 std::int16_t number{};
12170 return get_number(input_format, number) && sax->number_integer(number);
12171 }
12172
12173 case 'l':
12174 {
12175 std::int32_t number{};
12176 return get_number(input_format, number) && sax->number_integer(number);
12177 }
12178
12179 case 'L':
12180 {
12181 std::int64_t number{};
12182 return get_number(input_format, number) && sax->number_integer(number);
12183 }
12184
12185 case 'u':
12186 {
12187 if (input_format != input_format_t::bjdata)
12188 {
12189 break;
12190 }
12191 std::uint16_t number{};
12192 return get_number(input_format, number) && sax->number_unsigned(number);
12193 }
12194
12195 case 'm':
12196 {
12197 if (input_format != input_format_t::bjdata)
12198 {
12199 break;
12200 }
12201 std::uint32_t number{};
12202 return get_number(input_format, number) && sax->number_unsigned(number);
12203 }
12204
12205 case 'M':
12206 {
12207 if (input_format != input_format_t::bjdata)
12208 {
12209 break;
12210 }
12211 std::uint64_t number{};
12212 return get_number(input_format, number) && sax->number_unsigned(number);
12213 }
12214
12215 case 'h':
12216 {
12217 if (input_format != input_format_t::bjdata)
12218 {
12219 break;
12220 }
12221 const auto byte1_raw = get();
12222 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12223 {
12224 return false;
12225 }
12226 const auto byte2_raw = get();
12227 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12228 {
12229 return false;
12230 }
12231
12232 const auto byte1 = static_cast<unsigned char>(byte1_raw);
12233 const auto byte2 = static_cast<unsigned char>(byte2_raw);
12234
12235 // Code from RFC 7049, Appendix D, Figure 3:
12236 // As half-precision floating-point numbers were only added
12237 // to IEEE 754 in 2008, today's programming platforms often
12238 // still only have limited support for them. It is very
12239 // easy to include at least decoding support for them even
12240 // without such support. An example of a small decoder for
12241 // half-precision floating-point numbers in the C language
12242 // is shown in Fig. 3.
12243 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12244 const double val = [&half]
12245 {
12246 const int exp = (half >> 10u) & 0x1Fu;
12247 const unsigned int mant = half & 0x3FFu;
12248 JSON_ASSERT(0 <= exp&& exp <= 32);
12249 JSON_ASSERT(mant <= 1024);
12250 switch (exp)
12251 {
12252 case 0:
12253 return std::ldexp(mant, -24);
12254 case 31:
12255 return (mant == 0)
12256 ? std::numeric_limits<double>::infinity()
12257 : std::numeric_limits<double>::quiet_NaN();
12258 default:
12259 return std::ldexp(mant + 1024, exp - 25);
12260 }
12261 }();
12262 return sax->number_float((half & 0x8000u) != 0
12263 ? static_cast<number_float_t>(-val)
12264 : static_cast<number_float_t>(val), "");
12265 }
12266
12267 case 'd':
12268 {
12269 float number{};
12270 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12271 }
12272
12273 case 'D':
12274 {
12275 double number{};
12276 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12277 }
12278
12279 case 'H':
12280 {
12281 return get_ubjson_high_precision_number();
12282 }
12283
12284 case 'C': // char
12285 {
12286 get();
12287 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12288 {
12289 return false;
12290 }
12291 if (JSON_HEDLEY_UNLIKELY(current > 127))
12292 {
12293 auto last_token = get_token_string();
12294 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12295 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12296 }
12297 string_t s(1, static_cast<typename string_t::value_type>(current));
12298 return sax->string(s);
12299 }
12300
12301 case 'S': // string
12302 {
12303 string_t s;
12304 return get_ubjson_string(s) && sax->string(s);
12305 }
12306
12307 case '[': // array
12308 return get_ubjson_array();
12309
12310 case '{': // object
12311 return get_ubjson_object();
12312
12313 default: // anything else
12314 break;
12315 }
12316 auto last_token = get_token_string();
12317 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
12318 }
12319
12323 bool get_ubjson_array()
12324 {
12325 std::pair<std::size_t, char_int_type> size_and_type;
12326 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12327 {
12328 return false;
12329 }
12330
12331 // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
12332 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12333
12334 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12335 {
12336 size_and_type.second &= ~(static_cast<char_int_type>(1) << 8); // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
12337 auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
12338 {
12339 return p.first < t;
12340 });
12341 string_t key = "_ArrayType_";
12342 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12343 {
12344 auto last_token = get_token_string();
12345 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12346 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12347 }
12348
12349 string_t type = it->second; // sax->string() takes a reference
12350 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12351 {
12352 return false;
12353 }
12354
12355 if (size_and_type.second == 'C' || size_and_type.second == 'B')
12356 {
12357 size_and_type.second = 'U';
12358 }
12359
12360 key = "_ArrayData_";
12361 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12362 {
12363 return false;
12364 }
12365
12366 for (std::size_t i = 0; i < size_and_type.first; ++i)
12367 {
12368 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12369 {
12370 return false;
12371 }
12372 }
12373
12374 return (sax->end_array() && sax->end_object());
12375 }
12376
12377 // If BJData type marker is 'B' decode as binary
12378 if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12379 {
12380 binary_t result;
12381 return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12382 }
12383
12384 if (size_and_type.first != npos)
12385 {
12386 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12387 {
12388 return false;
12389 }
12390
12391 if (size_and_type.second != 0)
12392 {
12393 if (size_and_type.second != 'N')
12394 {
12395 for (std::size_t i = 0; i < size_and_type.first; ++i)
12396 {
12397 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12398 {
12399 return false;
12400 }
12401 }
12402 }
12403 }
12404 else
12405 {
12406 for (std::size_t i = 0; i < size_and_type.first; ++i)
12407 {
12408 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12409 {
12410 return false;
12411 }
12412 }
12413 }
12414 }
12415 else
12416 {
12417 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12418 {
12419 return false;
12420 }
12421
12422 while (current != ']')
12423 {
12424 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12425 {
12426 return false;
12427 }
12428 get_ignore_noop();
12429 }
12430 }
12431
12432 return sax->end_array();
12433 }
12434
12438 bool get_ubjson_object()
12439 {
12440 std::pair<std::size_t, char_int_type> size_and_type;
12441 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12442 {
12443 return false;
12444 }
12445
12446 // do not accept ND-array size in objects in BJData
12447 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12448 {
12449 auto last_token = get_token_string();
12450 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12451 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12452 }
12453
12454 string_t key;
12455 if (size_and_type.first != npos)
12456 {
12457 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12458 {
12459 return false;
12460 }
12461
12462 if (size_and_type.second != 0)
12463 {
12464 for (std::size_t i = 0; i < size_and_type.first; ++i)
12465 {
12466 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12467 {
12468 return false;
12469 }
12470 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12471 {
12472 return false;
12473 }
12474 key.clear();
12475 }
12476 }
12477 else
12478 {
12479 for (std::size_t i = 0; i < size_and_type.first; ++i)
12480 {
12481 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12482 {
12483 return false;
12484 }
12485 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12486 {
12487 return false;
12488 }
12489 key.clear();
12490 }
12491 }
12492 }
12493 else
12494 {
12495 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12496 {
12497 return false;
12498 }
12499
12500 while (current != '}')
12501 {
12502 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12503 {
12504 return false;
12505 }
12506 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12507 {
12508 return false;
12509 }
12510 get_ignore_noop();
12511 key.clear();
12512 }
12513 }
12514
12515 return sax->end_object();
12516 }
12517
12518 // Note, no reader for UBJSON binary types is implemented because they do
12519 // not exist
12520
12521 bool get_ubjson_high_precision_number()
12522 {
12523 // get the size of the following number string
12524 std::size_t size{};
12525 bool no_ndarray = true;
12526 auto res = get_ubjson_size_value(size, no_ndarray);
12527 if (JSON_HEDLEY_UNLIKELY(!res))
12528 {
12529 return res;
12530 }
12531
12532 // get number string
12533 std::vector<char> number_vector;
12534 for (std::size_t i = 0; i < size; ++i)
12535 {
12536 get();
12537 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12538 {
12539 return false;
12540 }
12541 number_vector.push_back(static_cast<char>(current));
12542 }
12543
12544 // parse number string
12545 using ia_type = decltype(detail::input_adapter(number_vector));
12546 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12547 const auto result_number = number_lexer.scan();
12548 const auto number_string = number_lexer.get_token_string();
12549 const auto result_remainder = number_lexer.scan();
12550
12551 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12552
12553 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12554 {
12555 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12556 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12557 }
12558
12559 switch (result_number)
12560 {
12561 case token_type::value_integer:
12562 return sax->number_integer(number_lexer.get_number_integer());
12563 case token_type::value_unsigned:
12564 return sax->number_unsigned(number_lexer.get_number_unsigned());
12565 case token_type::value_float:
12566 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12567 case token_type::uninitialized:
12568 case token_type::literal_true:
12569 case token_type::literal_false:
12570 case token_type::literal_null:
12571 case token_type::value_string:
12572 case token_type::begin_array:
12573 case token_type::begin_object:
12574 case token_type::end_array:
12575 case token_type::end_object:
12576 case token_type::name_separator:
12577 case token_type::value_separator:
12578 case token_type::parse_error:
12579 case token_type::end_of_input:
12580 case token_type::literal_or_value:
12581 default:
12582 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12583 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12584 }
12585 }
12586
12588 // Utility functions //
12590
12600 char_int_type get()
12601 {
12602 ++chars_read;
12603 return current = ia.get_character();
12604 }
12605
12614 template<class T>
12615 bool get_to(T& dest, const input_format_t format, const char* context)
12616 {
12617 auto new_chars_read = ia.get_elements(&dest);
12618 chars_read += new_chars_read;
12619 if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12620 {
12621 // in case of failure, advance position by 1 to report the failing location
12622 ++chars_read;
12623 sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12624 return false;
12625 }
12626 return true;
12627 }
12628
12632 char_int_type get_ignore_noop()
12633 {
12634 do
12635 {
12636 get();
12637 }
12638 while (current == 'N');
12639
12640 return current;
12641 }
12642
12643 template<class NumberType>
12644 static void byte_swap(NumberType& number)
12645 {
12646 constexpr std::size_t sz = sizeof(number);
12647#ifdef __cpp_lib_byteswap
12648 if constexpr (sz == 1)
12649 {
12650 return;
12651 }
12652 else if constexpr(std::is_integral_v<NumberType>)
12653 {
12654 number = std::byteswap(number);
12655 return;
12656 }
12657 else
12658 {
12659#endif
12660 auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12661 for (std::size_t i = 0; i < sz / 2; ++i)
12662 {
12663 std::swap(ptr[i], ptr[sz - i - 1]);
12664 }
12665#ifdef __cpp_lib_byteswap
12666 }
12667#endif
12668 }
12669
12670 /*
12671 @brief read a number from the input
12672
12673 @tparam NumberType the type of the number
12674 @param[in] format the current format (for diagnostics)
12675 @param[out] result number of type @a NumberType
12676
12677 @return whether conversion completed
12678
12679 @note This function needs to respect the system's endianness, because
12680 bytes in CBOR, MessagePack, and UBJSON are stored in network order
12681 (big endian) and therefore need reordering on little endian systems.
12682 On the other hand, BSON and BJData use little endian and should reorder
12683 on big endian systems.
12684 */
12685 template<typename NumberType, bool InputIsLittleEndian = false>
12686 bool get_number(const input_format_t format, NumberType& result)
12687 {
12688 // read in the original format
12689
12690 if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12691 {
12692 return false;
12693 }
12694 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12695 {
12696 byte_swap(result);
12697 }
12698 return true;
12699 }
12700
12715 template<typename NumberType>
12716 bool get_string(const input_format_t format,
12717 const NumberType len,
12718 string_t& result)
12719 {
12720 bool success = true;
12721 for (NumberType i = 0; i < len; i++)
12722 {
12723 get();
12724 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12725 {
12726 success = false;
12727 break;
12728 }
12729 result.push_back(static_cast<typename string_t::value_type>(current));
12730 }
12731 return success;
12732 }
12733
12748 template<typename NumberType>
12749 bool get_binary(const input_format_t format,
12750 const NumberType len,
12751 binary_t& result)
12752 {
12753 bool success = true;
12754 for (NumberType i = 0; i < len; i++)
12755 {
12756 get();
12757 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12758 {
12759 success = false;
12760 break;
12761 }
12762 result.push_back(static_cast<std::uint8_t>(current));
12763 }
12764 return success;
12765 }
12766
12773 bool unexpect_eof(const input_format_t format, const char* context) const
12774 {
12775 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12776 {
12777 return sax->parse_error(chars_read, "<end of file>",
12778 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12779 }
12780 return true;
12781 }
12782
12786 std::string get_token_string() const
12787 {
12788 std::array<char, 3> cr{{}};
12789 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12790 return std::string{cr.data()};
12791 }
12792
12799 std::string exception_message(const input_format_t format,
12800 const std::string& detail,
12801 const std::string& context) const
12802 {
12803 std::string error_msg = "syntax error while parsing ";
12804
12805 switch (format)
12806 {
12807 case input_format_t::cbor:
12808 error_msg += "CBOR";
12809 break;
12810
12811 case input_format_t::msgpack:
12812 error_msg += "MessagePack";
12813 break;
12814
12815 case input_format_t::ubjson:
12816 error_msg += "UBJSON";
12817 break;
12818
12819 case input_format_t::bson:
12820 error_msg += "BSON";
12821 break;
12822
12823 case input_format_t::bjdata:
12824 error_msg += "BJData";
12825 break;
12826
12827 case input_format_t::json: // LCOV_EXCL_LINE
12828 default: // LCOV_EXCL_LINE
12829 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12830 }
12831
12832 return concat(error_msg, ' ', context, ": ", detail);
12833 }
12834
12835 private:
12836 static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12837
12839 InputAdapterType ia;
12840
12842 char_int_type current = char_traits<char_type>::eof();
12843
12845 std::size_t chars_read = 0;
12846
12848 const bool is_little_endian = little_endianness();
12849
12851 const input_format_t input_format = input_format_t::json;
12852
12854 json_sax_t* sax = nullptr;
12855
12856 // excluded markers in bjdata optimized type
12857#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12858 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12859
12860#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12861 make_array<bjd_type>( \
12862 bjd_type{'B', "byte"}, \
12863 bjd_type{'C', "char"}, \
12864 bjd_type{'D', "double"}, \
12865 bjd_type{'I', "int16"}, \
12866 bjd_type{'L', "int64"}, \
12867 bjd_type{'M', "uint64"}, \
12868 bjd_type{'U', "uint8"}, \
12869 bjd_type{'d', "single"}, \
12870 bjd_type{'i', "int8"}, \
12871 bjd_type{'l', "int32"}, \
12872 bjd_type{'m', "uint32"}, \
12873 bjd_type{'u', "uint16"})
12874
12876 // lookup tables
12877 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12878 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12880
12881 using bjd_type = std::pair<char_int_type, string_t>;
12882 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12883 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12885
12886#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12887#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12888};
12889
12890#ifndef JSON_HAS_CPP_17
12891 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12892 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12893#endif
12894
12895} // namespace detail
12897
12898// #include <nlohmann/detail/input/input_adapters.hpp>
12899
12900// #include <nlohmann/detail/input/lexer.hpp>
12901
12902// #include <nlohmann/detail/input/parser.hpp>
12903// __ _____ _____ _____
12904// __| | __| | | | JSON for Modern C++
12905// | | |__ | | | | | | version 3.12.0
12906// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12907//
12908// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12909// SPDX-License-Identifier: MIT
12910
12911
12912
12913#include <cmath> // isfinite
12914#include <cstdint> // uint8_t
12915#include <functional> // function
12916#include <string> // string
12917#include <utility> // move
12918#include <vector> // vector
12919
12920// #include <nlohmann/detail/exceptions.hpp>
12921
12922// #include <nlohmann/detail/input/input_adapters.hpp>
12923
12924// #include <nlohmann/detail/input/json_sax.hpp>
12925
12926// #include <nlohmann/detail/input/lexer.hpp>
12927
12928// #include <nlohmann/detail/macro_scope.hpp>
12929
12930// #include <nlohmann/detail/meta/is_sax.hpp>
12931
12932// #include <nlohmann/detail/string_concat.hpp>
12933
12934// #include <nlohmann/detail/value_t.hpp>
12935
12936
12938namespace detail
12939{
12941// parser //
12943
12959
12960template<typename BasicJsonType>
12962 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12963
12969template<typename BasicJsonType, typename InputAdapterType>
12971{
12972 using number_integer_t = typename BasicJsonType::number_integer_t;
12973 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12974 using number_float_t = typename BasicJsonType::number_float_t;
12975 using string_t = typename BasicJsonType::string_t;
12977 using token_type = typename lexer_t::token_type;
12978
12979 public:
12981 explicit parser(InputAdapterType&& adapter,
12983 const bool allow_exceptions_ = true,
12984 const bool skip_comments = false)
12985 : callback(std::move(cb))
12986 , m_lexer(std::move(adapter), skip_comments)
12987 , allow_exceptions(allow_exceptions_)
12988 {
12989 // read first token
12990 get_token();
12991 }
12992
13003 void parse(const bool strict, BasicJsonType& result)
13004 {
13005 if (callback)
13006 {
13007 json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
13008 sax_parse_internal(&sdp);
13009
13010 // in strict mode, input must be completely read
13011 if (strict && (get_token() != token_type::end_of_input))
13012 {
13013 sdp.parse_error(m_lexer.get_position(),
13014 m_lexer.get_token_string(),
13015 parse_error::create(101, m_lexer.get_position(),
13016 exception_message(token_type::end_of_input, "value"), nullptr));
13017 }
13018
13019 // in case of an error, return a discarded value
13020 if (sdp.is_errored())
13021 {
13022 result = value_t::discarded;
13023 return;
13024 }
13025
13026 // set top-level value to null if it was discarded by the callback
13027 // function
13028 if (result.is_discarded())
13029 {
13030 result = nullptr;
13031 }
13032 }
13033 else
13034 {
13035 json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
13036 sax_parse_internal(&sdp);
13037
13038 // in strict mode, input must be completely read
13039 if (strict && (get_token() != token_type::end_of_input))
13040 {
13041 sdp.parse_error(m_lexer.get_position(),
13042 m_lexer.get_token_string(),
13043 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13044 }
13045
13046 // in case of an error, return a discarded value
13047 if (sdp.is_errored())
13048 {
13049 result = value_t::discarded;
13050 return;
13051 }
13052 }
13053
13054 result.assert_invariant();
13055 }
13056
13063 bool accept(const bool strict = true)
13064 {
13066 return sax_parse(&sax_acceptor, strict);
13067 }
13068
13069 template<typename SAX>
13071 bool sax_parse(SAX* sax, const bool strict = true)
13072 {
13074 const bool result = sax_parse_internal(sax);
13075
13076 // strict mode: next byte must be EOF
13077 if (result && strict && (get_token() != token_type::end_of_input))
13078 {
13079 return sax->parse_error(m_lexer.get_position(),
13080 m_lexer.get_token_string(),
13081 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13082 }
13083
13084 return result;
13085 }
13086
13087 private:
13088 template<typename SAX>
13090 bool sax_parse_internal(SAX* sax)
13091 {
13092 // stack to remember the hierarchy of structured values we are parsing
13093 // true = array; false = object
13094 std::vector<bool> states;
13095 // value to avoid a goto (see comment where set to true)
13096 bool skip_to_state_evaluation = false;
13097
13098 while (true)
13099 {
13100 if (!skip_to_state_evaluation)
13101 {
13102 // invariant: get_token() was called before each iteration
13103 switch (last_token)
13104 {
13105 case token_type::begin_object:
13106 {
13107 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13108 {
13109 return false;
13110 }
13111
13112 // closing } -> we are done
13113 if (get_token() == token_type::end_object)
13114 {
13115 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13116 {
13117 return false;
13118 }
13119 break;
13120 }
13121
13122 // parse key
13123 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13124 {
13125 return sax->parse_error(m_lexer.get_position(),
13126 m_lexer.get_token_string(),
13127 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13128 }
13129 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13130 {
13131 return false;
13132 }
13133
13134 // parse separator (:)
13135 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13136 {
13137 return sax->parse_error(m_lexer.get_position(),
13138 m_lexer.get_token_string(),
13139 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13140 }
13141
13142 // remember we are now inside an object
13143 states.push_back(false);
13144
13145 // parse values
13146 get_token();
13147 continue;
13148 }
13149
13150 case token_type::begin_array:
13151 {
13152 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13153 {
13154 return false;
13155 }
13156
13157 // closing ] -> we are done
13158 if (get_token() == token_type::end_array)
13159 {
13160 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13161 {
13162 return false;
13163 }
13164 break;
13165 }
13166
13167 // remember we are now inside an array
13168 states.push_back(true);
13169
13170 // parse values (no need to call get_token)
13171 continue;
13172 }
13173
13174 case token_type::value_float:
13175 {
13176 const auto res = m_lexer.get_number_float();
13177
13178 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13179 {
13180 return sax->parse_error(m_lexer.get_position(),
13181 m_lexer.get_token_string(),
13182 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13183 }
13184
13185 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13186 {
13187 return false;
13188 }
13189
13190 break;
13191 }
13192
13193 case token_type::literal_false:
13194 {
13195 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13196 {
13197 return false;
13198 }
13199 break;
13200 }
13201
13202 case token_type::literal_null:
13203 {
13204 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13205 {
13206 return false;
13207 }
13208 break;
13209 }
13210
13211 case token_type::literal_true:
13212 {
13213 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13214 {
13215 return false;
13216 }
13217 break;
13218 }
13219
13220 case token_type::value_integer:
13221 {
13222 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13223 {
13224 return false;
13225 }
13226 break;
13227 }
13228
13229 case token_type::value_string:
13230 {
13231 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13232 {
13233 return false;
13234 }
13235 break;
13236 }
13237
13238 case token_type::value_unsigned:
13239 {
13240 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13241 {
13242 return false;
13243 }
13244 break;
13245 }
13246
13247 case token_type::parse_error:
13248 {
13249 // using "uninitialized" to avoid an "expected" message
13250 return sax->parse_error(m_lexer.get_position(),
13251 m_lexer.get_token_string(),
13252 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13253 }
13254 case token_type::end_of_input:
13255 {
13256 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13257 {
13258 return sax->parse_error(m_lexer.get_position(),
13259 m_lexer.get_token_string(),
13260 parse_error::create(101, m_lexer.get_position(),
13261 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13262 }
13263
13264 return sax->parse_error(m_lexer.get_position(),
13265 m_lexer.get_token_string(),
13266 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13267 }
13268 case token_type::uninitialized:
13269 case token_type::end_array:
13270 case token_type::end_object:
13271 case token_type::name_separator:
13272 case token_type::value_separator:
13273 case token_type::literal_or_value:
13274 default: // the last token was unexpected
13275 {
13276 return sax->parse_error(m_lexer.get_position(),
13277 m_lexer.get_token_string(),
13278 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13279 }
13280 }
13281 }
13282 else
13283 {
13284 skip_to_state_evaluation = false;
13285 }
13286
13287 // we reached this line after we successfully parsed a value
13288 if (states.empty())
13289 {
13290 // empty stack: we reached the end of the hierarchy: done
13291 return true;
13292 }
13293
13294 if (states.back()) // array
13295 {
13296 // comma -> next value
13297 if (get_token() == token_type::value_separator)
13298 {
13299 // parse a new value
13300 get_token();
13301 continue;
13302 }
13303
13304 // closing ]
13305 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13306 {
13307 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13308 {
13309 return false;
13310 }
13311
13312 // We are done with this array. Before we can parse a
13313 // new value, we need to evaluate the new state first.
13314 // By setting skip_to_state_evaluation to false, we
13315 // are effectively jumping to the beginning of this if.
13316 JSON_ASSERT(!states.empty());
13317 states.pop_back();
13318 skip_to_state_evaluation = true;
13319 continue;
13320 }
13321
13322 return sax->parse_error(m_lexer.get_position(),
13323 m_lexer.get_token_string(),
13324 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13325 }
13326
13327 // states.back() is false -> object
13328
13329 // comma -> next value
13330 if (get_token() == token_type::value_separator)
13331 {
13332 // parse key
13333 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
13334 {
13335 return sax->parse_error(m_lexer.get_position(),
13336 m_lexer.get_token_string(),
13337 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13338 }
13339
13340 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13341 {
13342 return false;
13343 }
13344
13345 // parse separator (:)
13346 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13347 {
13348 return sax->parse_error(m_lexer.get_position(),
13349 m_lexer.get_token_string(),
13350 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13351 }
13352
13353 // parse values
13354 get_token();
13355 continue;
13356 }
13357
13358 // closing }
13359 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13360 {
13361 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13362 {
13363 return false;
13364 }
13365
13366 // We are done with this object. Before we can parse a
13367 // new value, we need to evaluate the new state first.
13368 // By setting skip_to_state_evaluation to false, we
13369 // are effectively jumping to the beginning of this if.
13370 JSON_ASSERT(!states.empty());
13371 states.pop_back();
13372 skip_to_state_evaluation = true;
13373 continue;
13374 }
13375
13376 return sax->parse_error(m_lexer.get_position(),
13377 m_lexer.get_token_string(),
13378 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13379 }
13380 }
13381
13383 token_type get_token()
13384 {
13385 return last_token = m_lexer.scan();
13386 }
13387
13388 std::string exception_message(const token_type expected, const std::string& context)
13389 {
13390 std::string error_msg = "syntax error ";
13391
13392 if (!context.empty())
13393 {
13394 error_msg += concat("while parsing ", context, ' ');
13395 }
13396
13397 error_msg += "- ";
13398
13399 if (last_token == token_type::parse_error)
13400 {
13401 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13402 m_lexer.get_token_string(), '\'');
13403 }
13404 else
13405 {
13406 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13407 }
13408
13409 if (expected != token_type::uninitialized)
13410 {
13411 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13412 }
13413
13414 return error_msg;
13415 }
13416
13417 private:
13419 const parser_callback_t<BasicJsonType> callback = nullptr;
13421 token_type last_token = token_type::uninitialized;
13423 lexer_t m_lexer;
13425 const bool allow_exceptions = true;
13426};
13427
13428} // namespace detail
13430
13431// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13432// __ _____ _____ _____
13433// __| | __| | | | JSON for Modern C++
13434// | | |__ | | | | | | version 3.12.0
13435// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13436//
13437// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13438// SPDX-License-Identifier: MIT
13439
13440
13441
13442// #include <nlohmann/detail/abi_macros.hpp>
13443
13444// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13445// __ _____ _____ _____
13446// __| | __| | | | JSON for Modern C++
13447// | | |__ | | | | | | version 3.12.0
13448// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13449//
13450// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13451// SPDX-License-Identifier: MIT
13452
13453
13454
13455#include <cstddef> // ptrdiff_t
13456#include <limits> // numeric_limits
13457
13458// #include <nlohmann/detail/macro_scope.hpp>
13459
13460
13462namespace detail
13463{
13464
13465/*
13466@brief an iterator for primitive JSON types
13467
13468This class models an iterator for primitive JSON types (boolean, number,
13469string). Its only purpose is to allow the iterator/const_iterator classes
13470to "iterate" over primitive values. Internally, the iterator is modeled by
13471a `difference_type` variable. Value begin_value (`0`) models the begin and
13472end_value (`1`) models past the end.
13473*/
13475{
13476 private:
13477 using difference_type = std::ptrdiff_t;
13478 static constexpr difference_type begin_value = 0;
13479 static constexpr difference_type end_value = begin_value + 1;
13480
13483 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13484
13485 public:
13486 constexpr difference_type get_value() const noexcept
13487 {
13488 return m_it;
13489 }
13490
13492 void set_begin() noexcept
13493 {
13494 m_it = begin_value;
13495 }
13496
13498 void set_end() noexcept
13499 {
13500 m_it = end_value;
13501 }
13502
13504 constexpr bool is_begin() const noexcept
13505 {
13506 return m_it == begin_value;
13507 }
13508
13510 constexpr bool is_end() const noexcept
13511 {
13512 return m_it == end_value;
13513 }
13514
13515 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13516 {
13517 return lhs.m_it == rhs.m_it;
13518 }
13519
13520 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13521 {
13522 return lhs.m_it < rhs.m_it;
13523 }
13524
13525 primitive_iterator_t operator+(difference_type n) noexcept
13526 {
13527 auto result = *this;
13528 result += n;
13529 return result;
13530 }
13531
13532 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13533 {
13534 return lhs.m_it - rhs.m_it;
13535 }
13536
13538 {
13539 ++m_it;
13540 return *this;
13541 }
13542
13543 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13544 {
13545 auto result = *this;
13546 ++m_it;
13547 return result;
13548 }
13549
13551 {
13552 --m_it;
13553 return *this;
13554 }
13555
13556 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13557 {
13558 auto result = *this;
13559 --m_it;
13560 return result;
13561 }
13562
13563 primitive_iterator_t& operator+=(difference_type n) noexcept
13564 {
13565 m_it += n;
13566 return *this;
13567 }
13568
13569 primitive_iterator_t& operator-=(difference_type n) noexcept
13570 {
13571 m_it -= n;
13572 return *this;
13573 }
13574};
13575
13576} // namespace detail
13578
13579
13581namespace detail
13582{
13583
13590template<typename BasicJsonType> struct internal_iterator
13591{
13593 typename BasicJsonType::object_t::iterator object_iterator {};
13595 typename BasicJsonType::array_t::iterator array_iterator {};
13598};
13599
13600} // namespace detail
13602
13603// #include <nlohmann/detail/iterators/iter_impl.hpp>
13604// __ _____ _____ _____
13605// __| | __| | | | JSON for Modern C++
13606// | | |__ | | | | | | version 3.12.0
13607// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13608//
13609// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13610// SPDX-License-Identifier: MIT
13611
13612
13613
13614#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13615#include <type_traits> // conditional, is_const, remove_const
13616
13617// #include <nlohmann/detail/exceptions.hpp>
13618
13619// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13620
13621// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13622
13623// #include <nlohmann/detail/macro_scope.hpp>
13624
13625// #include <nlohmann/detail/meta/cpp_future.hpp>
13626
13627// #include <nlohmann/detail/meta/type_traits.hpp>
13628
13629// #include <nlohmann/detail/value_t.hpp>
13630
13631
13633namespace detail
13634{
13635
13636// forward declare to be able to friend it later on
13637template<typename IteratorType> class iteration_proxy;
13638template<typename IteratorType> class iteration_proxy_value;
13639
13656template<typename BasicJsonType>
13657class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13658{
13660 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13662 friend other_iter_impl;
13663 friend BasicJsonType;
13666
13667 using object_t = typename BasicJsonType::object_t;
13668 using array_t = typename BasicJsonType::array_t;
13669 // make sure BasicJsonType is basic_json or const basic_json
13671 "iter_impl only accepts (const) basic_json");
13672 // superficial check for the LegacyBidirectionalIterator named requirement
13673 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13674 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13675 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13676
13677 public:
13683 using iterator_category = std::bidirectional_iterator_tag;
13684
13686 using value_type = typename BasicJsonType::value_type;
13688 using difference_type = typename BasicJsonType::difference_type;
13690 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13691 typename BasicJsonType::const_pointer,
13692 typename BasicJsonType::pointer>::type;
13695 typename std::conditional<std::is_const<BasicJsonType>::value,
13696 typename BasicJsonType::const_reference,
13697 typename BasicJsonType::reference>::type;
13698
13699 iter_impl() = default;
13700 ~iter_impl() = default;
13701 iter_impl(iter_impl&&) noexcept = default;
13702 iter_impl& operator=(iter_impl&&) noexcept = default;
13703
13710 explicit iter_impl(pointer object) noexcept : m_object(object)
13711 {
13712 JSON_ASSERT(m_object != nullptr);
13713
13714 switch (m_object->m_data.m_type)
13715 {
13716 case value_t::object:
13717 {
13718 m_it.object_iterator = typename object_t::iterator();
13719 break;
13720 }
13721
13722 case value_t::array:
13723 {
13724 m_it.array_iterator = typename array_t::iterator();
13725 break;
13726 }
13727
13728 case value_t::null:
13729 case value_t::string:
13730 case value_t::boolean:
13734 case value_t::binary:
13735 case value_t::discarded:
13736 default:
13737 {
13738 m_it.primitive_iterator = primitive_iterator_t();
13739 break;
13740 }
13741 }
13742 }
13743
13752
13761 : m_object(other.m_object), m_it(other.m_it)
13762 {}
13763
13771 {
13772 if (&other != this)
13773 {
13774 m_object = other.m_object;
13775 m_it = other.m_it;
13776 }
13777 return *this;
13778 }
13779
13785 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13786 : m_object(other.m_object), m_it(other.m_it)
13787 {}
13788
13795 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13796 {
13797 m_object = other.m_object;
13798 m_it = other.m_it;
13799 return *this;
13800 }
13801
13807 void set_begin() noexcept
13808 {
13809 JSON_ASSERT(m_object != nullptr);
13810
13811 switch (m_object->m_data.m_type)
13812 {
13813 case value_t::object:
13814 {
13815 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13816 break;
13817 }
13818
13819 case value_t::array:
13820 {
13821 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13822 break;
13823 }
13824
13825 case value_t::null:
13826 {
13827 // set to end so begin()==end() is true: null is empty
13828 m_it.primitive_iterator.set_end();
13829 break;
13830 }
13831
13832 case value_t::string:
13833 case value_t::boolean:
13837 case value_t::binary:
13838 case value_t::discarded:
13839 default:
13840 {
13841 m_it.primitive_iterator.set_begin();
13842 break;
13843 }
13844 }
13845 }
13846
13851 void set_end() noexcept
13852 {
13853 JSON_ASSERT(m_object != nullptr);
13854
13855 switch (m_object->m_data.m_type)
13856 {
13857 case value_t::object:
13858 {
13859 m_it.object_iterator = m_object->m_data.m_value.object->end();
13860 break;
13861 }
13862
13863 case value_t::array:
13864 {
13865 m_it.array_iterator = m_object->m_data.m_value.array->end();
13866 break;
13867 }
13868
13869 case value_t::null:
13870 case value_t::string:
13871 case value_t::boolean:
13875 case value_t::binary:
13876 case value_t::discarded:
13877 default:
13878 {
13879 m_it.primitive_iterator.set_end();
13880 break;
13881 }
13882 }
13883 }
13884
13885 public:
13891 {
13892 JSON_ASSERT(m_object != nullptr);
13893
13894 switch (m_object->m_data.m_type)
13895 {
13896 case value_t::object:
13897 {
13898 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13899 return m_it.object_iterator->second;
13900 }
13901
13902 case value_t::array:
13903 {
13904 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13905 return *m_it.array_iterator;
13906 }
13907
13908 case value_t::null:
13909 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13910
13911 case value_t::string:
13912 case value_t::boolean:
13916 case value_t::binary:
13917 case value_t::discarded:
13918 default:
13919 {
13920 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13921 {
13922 return *m_object;
13923 }
13924
13925 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13926 }
13927 }
13928 }
13929
13935 {
13936 JSON_ASSERT(m_object != nullptr);
13937
13938 switch (m_object->m_data.m_type)
13939 {
13940 case value_t::object:
13941 {
13942 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13943 return &(m_it.object_iterator->second);
13944 }
13945
13946 case value_t::array:
13947 {
13948 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13949 return &*m_it.array_iterator;
13950 }
13951
13952 case value_t::null:
13953 case value_t::string:
13954 case value_t::boolean:
13958 case value_t::binary:
13959 case value_t::discarded:
13960 default:
13961 {
13962 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13963 {
13964 return m_object;
13965 }
13966
13967 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13968 }
13969 }
13970 }
13971
13976 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13977 {
13978 auto result = *this;
13979 ++(*this);
13980 return result;
13981 }
13982
13988 {
13989 JSON_ASSERT(m_object != nullptr);
13990
13991 switch (m_object->m_data.m_type)
13992 {
13993 case value_t::object:
13994 {
13995 std::advance(m_it.object_iterator, 1);
13996 break;
13997 }
13998
13999 case value_t::array:
14000 {
14001 std::advance(m_it.array_iterator, 1);
14002 break;
14003 }
14004
14005 case value_t::null:
14006 case value_t::string:
14007 case value_t::boolean:
14011 case value_t::binary:
14012 case value_t::discarded:
14013 default:
14014 {
14015 ++m_it.primitive_iterator;
14016 break;
14017 }
14018 }
14019
14020 return *this;
14021 }
14022
14027 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
14028 {
14029 auto result = *this;
14030 --(*this);
14031 return result;
14032 }
14033
14039 {
14040 JSON_ASSERT(m_object != nullptr);
14041
14042 switch (m_object->m_data.m_type)
14043 {
14044 case value_t::object:
14045 {
14046 std::advance(m_it.object_iterator, -1);
14047 break;
14048 }
14049
14050 case value_t::array:
14051 {
14052 std::advance(m_it.array_iterator, -1);
14053 break;
14054 }
14055
14056 case value_t::null:
14057 case value_t::string:
14058 case value_t::boolean:
14062 case value_t::binary:
14063 case value_t::discarded:
14064 default:
14065 {
14066 --m_it.primitive_iterator;
14067 break;
14068 }
14069 }
14070
14071 return *this;
14072 }
14073
14078 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
14079 bool operator==(const IterImpl& other) const
14080 {
14081 // if objects are not the same, the comparison is undefined
14082 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14083 {
14084 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14085 }
14086
14087 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14088 if (m_object == nullptr)
14089 {
14090 return true;
14091 }
14092
14093 switch (m_object->m_data.m_type)
14094 {
14095 case value_t::object:
14096 return (m_it.object_iterator == other.m_it.object_iterator);
14097
14098 case value_t::array:
14099 return (m_it.array_iterator == other.m_it.array_iterator);
14100
14101 case value_t::null:
14102 case value_t::string:
14103 case value_t::boolean:
14107 case value_t::binary:
14108 case value_t::discarded:
14109 default:
14110 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14111 }
14112 }
14113
14118 template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
14119 bool operator!=(const IterImpl& other) const
14120 {
14121 return !operator==(other);
14122 }
14123
14128 bool operator<(const iter_impl& other) const
14129 {
14130 // if objects are not the same, the comparison is undefined
14131 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14132 {
14133 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14134 }
14135
14136 // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14137 if (m_object == nullptr)
14138 {
14139 // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14140 return false;
14141 }
14142
14143 switch (m_object->m_data.m_type)
14144 {
14145 case value_t::object:
14146 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14147
14148 case value_t::array:
14149 return (m_it.array_iterator < other.m_it.array_iterator);
14150
14151 case value_t::null:
14152 case value_t::string:
14153 case value_t::boolean:
14157 case value_t::binary:
14158 case value_t::discarded:
14159 default:
14160 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14161 }
14162 }
14163
14168 bool operator<=(const iter_impl& other) const
14169 {
14170 return !other.operator < (*this);
14171 }
14172
14177 bool operator>(const iter_impl& other) const
14178 {
14179 return !operator<=(other);
14180 }
14181
14186 bool operator>=(const iter_impl& other) const
14187 {
14188 return !operator<(other);
14189 }
14190
14196 {
14197 JSON_ASSERT(m_object != nullptr);
14198
14199 switch (m_object->m_data.m_type)
14200 {
14201 case value_t::object:
14202 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14203
14204 case value_t::array:
14205 {
14206 std::advance(m_it.array_iterator, i);
14207 break;
14208 }
14209
14210 case value_t::null:
14211 case value_t::string:
14212 case value_t::boolean:
14216 case value_t::binary:
14217 case value_t::discarded:
14218 default:
14219 {
14220 m_it.primitive_iterator += i;
14221 break;
14222 }
14223 }
14224
14225 return *this;
14226 }
14227
14233 {
14234 return operator+=(-i);
14235 }
14236
14242 {
14243 auto result = *this;
14244 result += i;
14245 return result;
14246 }
14247
14253 {
14254 auto result = it;
14255 result += i;
14256 return result;
14257 }
14258
14264 {
14265 auto result = *this;
14266 result -= i;
14267 return result;
14268 }
14269
14275 {
14276 JSON_ASSERT(m_object != nullptr);
14277
14278 switch (m_object->m_data.m_type)
14279 {
14280 case value_t::object:
14281 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14282
14283 case value_t::array:
14284 return m_it.array_iterator - other.m_it.array_iterator;
14285
14286 case value_t::null:
14287 case value_t::string:
14288 case value_t::boolean:
14292 case value_t::binary:
14293 case value_t::discarded:
14294 default:
14295 return m_it.primitive_iterator - other.m_it.primitive_iterator;
14296 }
14297 }
14298
14304 {
14305 JSON_ASSERT(m_object != nullptr);
14306
14307 switch (m_object->m_data.m_type)
14308 {
14309 case value_t::object:
14310 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14311
14312 case value_t::array:
14313 return *std::next(m_it.array_iterator, n);
14314
14315 case value_t::null:
14316 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14317
14318 case value_t::string:
14319 case value_t::boolean:
14323 case value_t::binary:
14324 case value_t::discarded:
14325 default:
14326 {
14327 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14328 {
14329 return *m_object;
14330 }
14331
14332 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14333 }
14334 }
14335 }
14336
14341 const typename object_t::key_type& key() const
14342 {
14343 JSON_ASSERT(m_object != nullptr);
14344
14345 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14346 {
14347 return m_it.object_iterator->first;
14348 }
14349
14350 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14351 }
14352
14358 {
14359 return operator*();
14360 }
14361
14364 pointer m_object = nullptr;
14367};
14368
14369} // namespace detail
14371
14372// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14373
14374// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14375// __ _____ _____ _____
14376// __| | __| | | | JSON for Modern C++
14377// | | |__ | | | | | | version 3.12.0
14378// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14379//
14380// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14381// SPDX-License-Identifier: MIT
14382
14383
14384
14385#include <cstddef> // ptrdiff_t
14386#include <iterator> // reverse_iterator
14387#include <utility> // declval
14388
14389// #include <nlohmann/detail/abi_macros.hpp>
14390
14391
14393namespace detail
14394{
14395
14397// reverse_iterator //
14399
14418template<typename Base>
14419class json_reverse_iterator : public std::reverse_iterator<Base>
14420{
14421 public:
14422 using difference_type = std::ptrdiff_t;
14424 using base_iterator = std::reverse_iterator<Base>;
14426 using reference = typename Base::reference;
14427
14429 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14430 : base_iterator(it) {}
14431
14433 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14434
14436 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14437 {
14438 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14439 }
14440
14443 {
14444 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14445 }
14446
14448 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14449 {
14450 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14451 }
14452
14455 {
14456 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14457 }
14458
14461 {
14462 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14463 }
14464
14467 {
14468 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14469 }
14470
14473 {
14474 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14475 }
14476
14479 {
14480 return base_iterator(*this) - base_iterator(other);
14481 }
14482
14485 {
14486 return *(this->operator+(n));
14487 }
14488
14490 auto key() const -> decltype(std::declval<Base>().key())
14491 {
14492 auto it = --this->base();
14493 return it.key();
14494 }
14495
14498 {
14499 auto it = --this->base();
14500 return it.operator * ();
14501 }
14502};
14503
14504} // namespace detail
14506
14507// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14508
14509// #include <nlohmann/detail/json_custom_base_class.hpp>
14510// __ _____ _____ _____
14511// __| | __| | | | JSON for Modern C++
14512// | | |__ | | | | | | version 3.12.0
14513// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14514//
14515// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14516// SPDX-License-Identifier: MIT
14517
14518
14519
14520#include <type_traits> // conditional, is_same
14521
14522// #include <nlohmann/detail/abi_macros.hpp>
14523
14524
14526namespace detail
14527{
14528
14540
14541template<class T>
14542using json_base_class = typename std::conditional <
14543 std::is_same<T, void>::value,
14545 T
14546 >::type;
14547
14548} // namespace detail
14550
14551// #include <nlohmann/detail/json_pointer.hpp>
14552// __ _____ _____ _____
14553// __| | __| | | | JSON for Modern C++
14554// | | |__ | | | | | | version 3.12.0
14555// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14556//
14557// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14558// SPDX-License-Identifier: MIT
14559
14560
14561
14562#include <algorithm> // all_of
14563#include <cctype> // isdigit
14564#include <cerrno> // errno, ERANGE
14565#include <cstdlib> // strtoull
14566#ifndef JSON_NO_IO
14567 #include <iosfwd> // ostream
14568#endif // JSON_NO_IO
14569#include <limits> // max
14570#include <numeric> // accumulate
14571#include <string> // string
14572#include <utility> // move
14573#include <vector> // vector
14574
14575// #include <nlohmann/detail/exceptions.hpp>
14576
14577// #include <nlohmann/detail/macro_scope.hpp>
14578
14579// #include <nlohmann/detail/string_concat.hpp>
14580
14581// #include <nlohmann/detail/string_escape.hpp>
14582
14583// #include <nlohmann/detail/value_t.hpp>
14584
14585
14587
14590template<typename RefStringType>
14592{
14593 // allow basic_json to access private members
14595 friend class basic_json;
14596
14597 template<typename>
14598 friend class json_pointer;
14599
14600 template<typename T>
14601 struct string_t_helper
14602 {
14603 using type = T;
14604 };
14605
14607 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14608 {
14609 using type = StringType;
14610 };
14611
14612 public:
14613 // for backwards compatibility accept BasicJsonType
14614 using string_t = typename string_t_helper<RefStringType>::type;
14615
14618 explicit json_pointer(const string_t& s = "")
14619 : reference_tokens(split(s))
14620 {}
14621
14625 {
14626 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14627 string_t{},
14628 [](const string_t& a, const string_t& b)
14629 {
14630 return detail::concat(a, '/', detail::escape(b));
14631 });
14632 }
14633
14637 operator string_t() const
14638 {
14639 return to_string();
14640 }
14641
14642#ifndef JSON_NO_IO
14645 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14646 {
14647 o << ptr.to_string();
14648 return o;
14649 }
14650#endif
14651
14655 {
14656 reference_tokens.insert(reference_tokens.end(),
14657 ptr.reference_tokens.begin(),
14658 ptr.reference_tokens.end());
14659 return *this;
14660 }
14661
14665 {
14666 push_back(std::move(token));
14667 return *this;
14668 }
14669
14672 json_pointer& operator/=(std::size_t array_idx)
14673 {
14674 return *this /= std::to_string(array_idx);
14675 }
14676
14680 const json_pointer& rhs)
14681 {
14682 return json_pointer(lhs) /= rhs;
14683 }
14684
14687 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14688 {
14689 return json_pointer(lhs) /= std::move(token);
14690 }
14691
14694 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14695 {
14696 return json_pointer(lhs) /= array_idx;
14697 }
14698
14702 {
14703 if (empty())
14704 {
14705 return *this;
14706 }
14707
14708 json_pointer res = *this;
14709 res.pop_back();
14710 return res;
14711 }
14712
14716 {
14718 {
14719 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14720 }
14721
14722 reference_tokens.pop_back();
14723 }
14724
14727 const string_t& back() const
14728 {
14730 {
14731 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14732 }
14733
14734 return reference_tokens.back();
14735 }
14736
14739 void push_back(const string_t& token)
14740 {
14741 reference_tokens.push_back(token);
14742 }
14743
14746 void push_back(string_t&& token)
14747 {
14748 reference_tokens.push_back(std::move(token));
14749 }
14750
14753 bool empty() const noexcept
14754 {
14755 return reference_tokens.empty();
14756 }
14757
14758 private:
14769 template<typename BasicJsonType>
14770 static typename BasicJsonType::size_type array_index(const string_t& s)
14771 {
14772 using size_type = typename BasicJsonType::size_type;
14773
14774 // error condition (cf. RFC 6901, Sect. 4)
14775 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14776 {
14777 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14778 }
14779
14780 // error condition (cf. RFC 6901, Sect. 4)
14781 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14782 {
14783 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14784 }
14785
14786 const char* p = s.c_str();
14787 char* p_end = nullptr; // NOLINT(misc-const-correctness)
14788 errno = 0; // strtoull doesn't reset errno
14789 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14790 if (p == p_end // invalid input or empty string
14791 || errno == ERANGE // out of range
14792 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14793 {
14794 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14795 }
14796
14797 // only triggered on special platforms (like 32bit), see also
14798 // https://github.com/nlohmann/json/pull/2203
14799 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14800 {
14801 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14802 }
14803
14804 return static_cast<size_type>(res);
14805 }
14806
14808 json_pointer top() const
14809 {
14810 if (JSON_HEDLEY_UNLIKELY(empty()))
14811 {
14812 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14813 }
14814
14815 json_pointer result = *this;
14816 result.reference_tokens = {reference_tokens[0]};
14817 return result;
14818 }
14819
14820 private:
14829 template<typename BasicJsonType>
14830 BasicJsonType& get_and_create(BasicJsonType& j) const
14831 {
14832 auto* result = &j;
14833
14834 // in case no reference tokens exist, return a reference to the JSON value
14835 // j which will be overwritten by a primitive value
14836 for (const auto& reference_token : reference_tokens)
14837 {
14838 switch (result->type())
14839 {
14841 {
14842 if (reference_token == "0")
14843 {
14844 // start a new array if the reference token is 0
14845 result = &result->operator[](0);
14846 }
14847 else
14848 {
14849 // start a new object otherwise
14850 result = &result->operator[](reference_token);
14851 }
14852 break;
14853 }
14854
14856 {
14857 // create an entry in the object
14858 result = &result->operator[](reference_token);
14859 break;
14860 }
14861
14863 {
14864 // create an entry in the array
14865 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14866 break;
14867 }
14868
14869 /*
14870 The following code is only reached if there exists a reference
14871 token _and_ the current value is primitive. In this case, we have
14872 an error situation, because primitive values may only occur as
14873 a single value; that is, with an empty list of reference tokens.
14874 */
14882 default:
14883 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14884 }
14885 }
14886
14887 return *result;
14888 }
14889
14909 template<typename BasicJsonType>
14910 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14911 {
14912 for (const auto& reference_token : reference_tokens)
14913 {
14914 // convert null values to arrays or objects before continuing
14915 if (ptr->is_null())
14916 {
14917 // check if the reference token is a number
14918 const bool nums =
14919 std::all_of(reference_token.begin(), reference_token.end(),
14920 [](const unsigned char x)
14921 {
14922 return std::isdigit(x);
14923 });
14924
14925 // change value to an array for numbers or "-" or to object otherwise
14926 *ptr = (nums || reference_token == "-")
14928 : detail::value_t::object;
14929 }
14930
14931 switch (ptr->type())
14932 {
14934 {
14935 // use unchecked object access
14936 ptr = &ptr->operator[](reference_token);
14937 break;
14938 }
14939
14941 {
14942 if (reference_token == "-")
14943 {
14944 // explicitly treat "-" as index beyond the end
14945 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14946 }
14947 else
14948 {
14949 // convert array index to number; unchecked access
14950 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14951 }
14952 break;
14953 }
14954
14963 default:
14964 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14965 }
14966 }
14967
14968 return *ptr;
14969 }
14970
14977 template<typename BasicJsonType>
14978 BasicJsonType& get_checked(BasicJsonType* ptr) const
14979 {
14980 for (const auto& reference_token : reference_tokens)
14981 {
14982 switch (ptr->type())
14983 {
14985 {
14986 // note: at performs range check
14987 ptr = &ptr->at(reference_token);
14988 break;
14989 }
14990
14992 {
14993 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14994 {
14995 // "-" always fails the range check
14997 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14998 ") is out of range"), ptr));
14999 }
15000
15001 // note: at performs range check
15002 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15003 break;
15004 }
15005
15014 default:
15015 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15016 }
15017 }
15018
15019 return *ptr;
15020 }
15021
15035 template<typename BasicJsonType>
15036 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
15037 {
15038 for (const auto& reference_token : reference_tokens)
15039 {
15040 switch (ptr->type())
15041 {
15043 {
15044 // use unchecked object access
15045 ptr = &ptr->operator[](reference_token);
15046 break;
15047 }
15048
15050 {
15051 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15052 {
15053 // "-" cannot be used for const access
15054 JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
15055 }
15056
15057 // use unchecked array access
15058 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15059 break;
15060 }
15061
15070 default:
15071 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15072 }
15073 }
15074
15075 return *ptr;
15076 }
15077
15084 template<typename BasicJsonType>
15085 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15086 {
15087 for (const auto& reference_token : reference_tokens)
15088 {
15089 switch (ptr->type())
15090 {
15092 {
15093 // note: at performs range check
15094 ptr = &ptr->at(reference_token);
15095 break;
15096 }
15097
15099 {
15100 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15101 {
15102 // "-" always fails the range check
15104 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15105 ") is out of range"), ptr));
15106 }
15107
15108 // note: at performs range check
15109 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15110 break;
15111 }
15112
15121 default:
15122 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15123 }
15124 }
15125
15126 return *ptr;
15127 }
15128
15133 template<typename BasicJsonType>
15134 bool contains(const BasicJsonType* ptr) const
15135 {
15136 for (const auto& reference_token : reference_tokens)
15137 {
15138 switch (ptr->type())
15139 {
15141 {
15142 if (!ptr->contains(reference_token))
15143 {
15144 // we did not find the key in the object
15145 return false;
15146 }
15147
15148 ptr = &ptr->operator[](reference_token);
15149 break;
15150 }
15151
15153 {
15154 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15155 {
15156 // "-" always fails the range check
15157 return false;
15158 }
15159 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15160 {
15161 // invalid char
15162 return false;
15163 }
15164 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15165 {
15166 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15167 {
15168 // the first char should be between '1' and '9'
15169 return false;
15170 }
15171 for (std::size_t i = 1; i < reference_token.size(); i++)
15172 {
15173 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15174 {
15175 // other char should be between '0' and '9'
15176 return false;
15177 }
15178 }
15179 }
15180
15181 const auto idx = array_index<BasicJsonType>(reference_token);
15182 if (idx >= ptr->size())
15183 {
15184 // index out of range
15185 return false;
15186 }
15187
15188 ptr = &ptr->operator[](idx);
15189 break;
15190 }
15191
15200 default:
15201 {
15202 // we do not expect primitive values if there is still a
15203 // reference token to process
15204 return false;
15205 }
15206 }
15207 }
15208
15209 // no reference token left means we found a primitive value
15210 return true;
15211 }
15212
15222 static std::vector<string_t> split(const string_t& reference_string)
15223 {
15224 std::vector<string_t> result;
15225
15226 // special case: empty reference string -> no reference tokens
15227 if (reference_string.empty())
15228 {
15229 return result;
15230 }
15231
15232 // check if a nonempty reference string begins with slash
15233 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15234 {
15235 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15236 }
15237
15238 // extract the reference tokens:
15239 // - slash: position of the last read slash (or end of string)
15240 // - start: position after the previous slash
15241 for (
15242 // search for the first slash after the first character
15243 std::size_t slash = reference_string.find_first_of('/', 1),
15244 // set the beginning of the first reference token
15245 start = 1;
15246 // we can stop if start == 0 (if slash == string_t::npos)
15247 start != 0;
15248 // set the beginning of the next reference token
15249 // (will eventually be 0 if slash == string_t::npos)
15250 start = (slash == string_t::npos) ? 0 : slash + 1,
15251 // find next slash
15252 slash = reference_string.find_first_of('/', start))
15253 {
15254 // use the text between the beginning of the reference token
15255 // (start) and the last slash (slash).
15256 auto reference_token = reference_string.substr(start, slash - start);
15257
15258 // check reference tokens are properly escaped
15259 for (std::size_t pos = reference_token.find_first_of('~');
15260 pos != string_t::npos;
15261 pos = reference_token.find_first_of('~', pos + 1))
15262 {
15263 JSON_ASSERT(reference_token[pos] == '~');
15264
15265 // ~ must be followed by 0 or 1
15266 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15267 (reference_token[pos + 1] != '0' &&
15268 reference_token[pos + 1] != '1')))
15269 {
15270 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15271 }
15272 }
15273
15274 // finally, store the reference token
15275 detail::unescape(reference_token);
15276 result.push_back(reference_token);
15277 }
15278
15279 return result;
15280 }
15281
15282 private:
15290 template<typename BasicJsonType>
15291 static void flatten(const string_t& reference_string,
15292 const BasicJsonType& value,
15293 BasicJsonType& result)
15294 {
15295 switch (value.type())
15296 {
15298 {
15299 if (value.m_data.m_value.array->empty())
15300 {
15301 // flatten empty array as null
15302 result[reference_string] = nullptr;
15303 }
15304 else
15305 {
15306 // iterate array and use index as a reference string
15307 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15308 {
15309 flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15310 value.m_data.m_value.array->operator[](i), result);
15311 }
15312 }
15313 break;
15314 }
15315
15317 {
15318 if (value.m_data.m_value.object->empty())
15319 {
15320 // flatten empty object as null
15321 result[reference_string] = nullptr;
15322 }
15323 else
15324 {
15325 // iterate object and use keys as reference string
15326 for (const auto& element : *value.m_data.m_value.object)
15327 {
15328 flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15329 }
15330 }
15331 break;
15332 }
15333
15342 default:
15343 {
15344 // add a primitive value with its reference string
15345 result[reference_string] = value;
15346 break;
15347 }
15348 }
15349 }
15350
15361 template<typename BasicJsonType>
15362 static BasicJsonType
15363 unflatten(const BasicJsonType& value)
15364 {
15365 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15366 {
15367 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15368 }
15369
15370 BasicJsonType result;
15371
15372 // iterate the JSON object values
15373 for (const auto& element : *value.m_data.m_value.object)
15374 {
15375 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15376 {
15377 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15378 }
15379
15380 // Assign the value to the reference pointed to by JSON pointer. Note
15381 // that if the JSON pointer is "" (i.e., points to the whole value),
15382 // function get_and_create returns a reference to the result itself.
15383 // An assignment will then create a primitive value.
15384 json_pointer(element.first).get_and_create(result) = element.second;
15385 }
15386
15387 return result;
15388 }
15389
15390 // can't use the conversion operator because of ambiguity
15391 json_pointer<string_t> convert() const&
15392 {
15393 json_pointer<string_t> result;
15394 result.reference_tokens = reference_tokens;
15395 return result;
15396 }
15397
15398 json_pointer<string_t> convert()&&
15399 {
15400 json_pointer<string_t> result;
15401 result.reference_tokens = std::move(reference_tokens);
15402 return result;
15403 }
15404
15405 public:
15406#if JSON_HAS_THREE_WAY_COMPARISON
15409 template<typename RefStringTypeRhs>
15410 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15411 {
15412 return reference_tokens == rhs.reference_tokens;
15413 }
15414
15417 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15418 bool operator==(const string_t& rhs) const
15419 {
15420 return *this == json_pointer(rhs);
15421 }
15422
15424 template<typename RefStringTypeRhs>
15425 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15426 {
15427 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15428 }
15429#else
15432 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15433 // NOLINTNEXTLINE(readability-redundant-declaration)
15434 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15435 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15436
15439 template<typename RefStringTypeLhs, typename StringType>
15440 // NOLINTNEXTLINE(readability-redundant-declaration)
15441 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15442 const StringType& rhs);
15443
15446 template<typename RefStringTypeRhs, typename StringType>
15447 // NOLINTNEXTLINE(readability-redundant-declaration)
15448 friend bool operator==(const StringType& lhs,
15449 const json_pointer<RefStringTypeRhs>& rhs);
15450
15453 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15454 // NOLINTNEXTLINE(readability-redundant-declaration)
15455 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15456 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15457
15460 template<typename RefStringTypeLhs, typename StringType>
15461 // NOLINTNEXTLINE(readability-redundant-declaration)
15462 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15463 const StringType& rhs);
15464
15467 template<typename RefStringTypeRhs, typename StringType>
15468 // NOLINTNEXTLINE(readability-redundant-declaration)
15469 friend bool operator!=(const StringType& lhs,
15470 const json_pointer<RefStringTypeRhs>& rhs);
15471
15473 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15474 // NOLINTNEXTLINE(readability-redundant-declaration)
15475 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15476 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15477#endif
15478
15479 private:
15481 std::vector<string_t> reference_tokens;
15482};
15483
15484#if !JSON_HAS_THREE_WAY_COMPARISON
15485// functions cannot be defined inside the class due to ODR violations
15486template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15488 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15489{
15490 return lhs.reference_tokens == rhs.reference_tokens;
15491}
15492
15493template<typename RefStringTypeLhs,
15494 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15496inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15497 const StringType& rhs)
15498{
15499 return lhs == json_pointer<RefStringTypeLhs>(rhs);
15500}
15501
15502template<typename RefStringTypeRhs,
15503 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15505inline bool operator==(const StringType& lhs,
15506 const json_pointer<RefStringTypeRhs>& rhs)
15507{
15508 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15509}
15510
15511template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15513 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15514{
15515 return !(lhs == rhs);
15516}
15517
15518template<typename RefStringTypeLhs,
15519 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15521inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15522 const StringType& rhs)
15523{
15524 return !(lhs == rhs);
15525}
15526
15527template<typename RefStringTypeRhs,
15528 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15530inline bool operator!=(const StringType& lhs,
15531 const json_pointer<RefStringTypeRhs>& rhs)
15532{
15533 return !(lhs == rhs);
15534}
15535
15536template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15538 const json_pointer<RefStringTypeRhs>& rhs) noexcept
15539{
15540 return lhs.reference_tokens < rhs.reference_tokens;
15541}
15542#endif
15543
15545
15546// #include <nlohmann/detail/json_ref.hpp>
15547// __ _____ _____ _____
15548// __| | __| | | | JSON for Modern C++
15549// | | |__ | | | | | | version 3.12.0
15550// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15551//
15552// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15553// SPDX-License-Identifier: MIT
15554
15555
15556
15557#include <initializer_list>
15558#include <utility>
15559
15560// #include <nlohmann/detail/abi_macros.hpp>
15561
15562// #include <nlohmann/detail/meta/type_traits.hpp>
15563
15564
15566namespace detail
15567{
15568
15569template<typename BasicJsonType>
15571{
15572 public:
15573 using value_type = BasicJsonType;
15574
15576 : owned_value(std::move(value))
15577 {}
15578
15580 : value_ref(&value)
15581 {}
15582
15583 json_ref(std::initializer_list<json_ref> init)
15584 : owned_value(init)
15585 {}
15586
15587 template <
15588 class... Args,
15589 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15590 json_ref(Args && ... args)
15591 : owned_value(std::forward<Args>(args)...)
15592 {}
15593
15594 // class should be movable only
15595 json_ref(json_ref&&) noexcept = default;
15596 json_ref(const json_ref&) = delete;
15597 json_ref& operator=(const json_ref&) = delete;
15598 json_ref& operator=(json_ref&&) = delete;
15599 ~json_ref() = default;
15600
15602 {
15603 if (value_ref == nullptr)
15604 {
15605 return std::move(owned_value);
15606 }
15607 return *value_ref;
15608 }
15609
15610 value_type const& operator*() const
15611 {
15612 return value_ref ? *value_ref : owned_value;
15613 }
15614
15615 value_type const* operator->() const
15616 {
15617 return &** this;
15618 }
15619
15620 private:
15621 mutable value_type owned_value = nullptr;
15622 value_type const* value_ref = nullptr;
15623};
15624
15625} // namespace detail
15627
15628// #include <nlohmann/detail/macro_scope.hpp>
15629
15630// #include <nlohmann/detail/string_concat.hpp>
15631
15632// #include <nlohmann/detail/string_escape.hpp>
15633
15634// #include <nlohmann/detail/string_utils.hpp>
15635
15636// #include <nlohmann/detail/meta/cpp_future.hpp>
15637
15638// #include <nlohmann/detail/meta/type_traits.hpp>
15639
15640// #include <nlohmann/detail/output/binary_writer.hpp>
15641// __ _____ _____ _____
15642// __| | __| | | | JSON for Modern C++
15643// | | |__ | | | | | | version 3.12.0
15644// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15645//
15646// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15647// SPDX-License-Identifier: MIT
15648
15649
15650
15651#include <algorithm> // reverse
15652#include <array> // array
15653#include <map> // map
15654#include <cmath> // isnan, isinf
15655#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15656#include <cstring> // memcpy
15657#include <limits> // numeric_limits
15658#include <string> // string
15659#include <utility> // move
15660#include <vector> // vector
15661
15662// #include <nlohmann/detail/input/binary_reader.hpp>
15663
15664// #include <nlohmann/detail/macro_scope.hpp>
15665
15666// #include <nlohmann/detail/output/output_adapters.hpp>
15667// __ _____ _____ _____
15668// __| | __| | | | JSON for Modern C++
15669// | | |__ | | | | | | version 3.12.0
15670// |_____|_____|_____|_|___| https://github.com/nlohmann/json
15671//
15672// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15673// SPDX-License-Identifier: MIT
15674
15675
15676
15677#include <algorithm> // copy
15678#include <cstddef> // size_t
15679#include <iterator> // back_inserter
15680#include <memory> // shared_ptr, make_shared
15681#include <string> // basic_string
15682#include <vector> // vector
15683
15684#ifndef JSON_NO_IO
15685 #include <ios> // streamsize
15686 #include <ostream> // basic_ostream
15687#endif // JSON_NO_IO
15688
15689// #include <nlohmann/detail/macro_scope.hpp>
15690
15691
15693namespace detail
15694{
15695
15697template<typename CharType> struct output_adapter_protocol
15698{
15699 virtual void write_character(CharType c) = 0;
15700 virtual void write_characters(const CharType* s, std::size_t length) = 0;
15701 virtual ~output_adapter_protocol() = default;
15702
15707 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15708};
15709
15711template<typename CharType>
15712using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15713
15715template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15717{
15718 public:
15719 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15720 : v(vec)
15721 {}
15722
15723 void write_character(CharType c) override
15724 {
15725 v.push_back(c);
15726 }
15727
15729 void write_characters(const CharType* s, std::size_t length) override
15730 {
15731 v.insert(v.end(), s, s + length);
15732 }
15733
15734 private:
15735 std::vector<CharType, AllocatorType>& v;
15736};
15737
15738#ifndef JSON_NO_IO
15740template<typename CharType>
15742{
15743 public:
15744 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15745 : stream(s)
15746 {}
15747
15748 void write_character(CharType c) override
15749 {
15750 stream.put(c);
15751 }
15752
15754 void write_characters(const CharType* s, std::size_t length) override
15755 {
15756 stream.write(s, static_cast<std::streamsize>(length));
15757 }
15758
15759 private:
15760 std::basic_ostream<CharType>& stream;
15761};
15762#endif // JSON_NO_IO
15763
15765template<typename CharType, typename StringType = std::basic_string<CharType>>
15767{
15768 public:
15769 explicit output_string_adapter(StringType& s) noexcept
15770 : str(s)
15771 {}
15772
15773 void write_character(CharType c) override
15774 {
15775 str.push_back(c);
15776 }
15777
15779 void write_characters(const CharType* s, std::size_t length) override
15780 {
15781 str.append(s, length);
15782 }
15783
15784 private:
15785 StringType& str;
15786};
15787
15788template<typename CharType, typename StringType = std::basic_string<CharType>>
15790{
15791 public:
15792 template<typename AllocatorType = std::allocator<CharType>>
15793 output_adapter(std::vector<CharType, AllocatorType>& vec)
15794 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15795
15796#ifndef JSON_NO_IO
15797 output_adapter(std::basic_ostream<CharType>& s)
15798 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15799#endif // JSON_NO_IO
15800
15801 output_adapter(StringType& s)
15802 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15803
15805 {
15806 return oa;
15807 }
15808
15809 private:
15810 output_adapter_t<CharType> oa = nullptr;
15811};
15812
15813} // namespace detail
15815
15816// #include <nlohmann/detail/string_concat.hpp>
15817
15818
15820namespace detail
15821{
15822
15825{
15828};
15829
15831// binary writer //
15833
15837template<typename BasicJsonType, typename CharType>
15839{
15840 using string_t = typename BasicJsonType::string_t;
15841 using binary_t = typename BasicJsonType::binary_t;
15842 using number_float_t = typename BasicJsonType::number_float_t;
15843
15844 public:
15850 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15851 {
15852 JSON_ASSERT(oa);
15853 }
15854
15859 void write_bson(const BasicJsonType& j)
15860 {
15861 switch (j.type())
15862 {
15863 case value_t::object:
15864 {
15865 write_bson_object(*j.m_data.m_value.object);
15866 break;
15867 }
15868
15869 case value_t::null:
15870 case value_t::array:
15871 case value_t::string:
15872 case value_t::boolean:
15876 case value_t::binary:
15877 case value_t::discarded:
15878 default:
15879 {
15880 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15881 }
15882 }
15883 }
15884
15888 void write_cbor(const BasicJsonType& j)
15889 {
15890 switch (j.type())
15891 {
15892 case value_t::null:
15893 {
15894 oa->write_character(to_char_type(0xF6));
15895 break;
15896 }
15897
15898 case value_t::boolean:
15899 {
15900 oa->write_character(j.m_data.m_value.boolean
15901 ? to_char_type(0xF5)
15902 : to_char_type(0xF4));
15903 break;
15904 }
15905
15907 {
15908 if (j.m_data.m_value.number_integer >= 0)
15909 {
15910 // CBOR does not differentiate between positive signed
15911 // integers and unsigned integers. Therefore, we used the
15912 // code from the value_t::number_unsigned case here.
15913 if (j.m_data.m_value.number_integer <= 0x17)
15914 {
15915 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15916 }
15917 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15918 {
15919 oa->write_character(to_char_type(0x18));
15920 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15921 }
15922 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15923 {
15924 oa->write_character(to_char_type(0x19));
15925 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15926 }
15927 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15928 {
15929 oa->write_character(to_char_type(0x1A));
15930 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15931 }
15932 else
15933 {
15934 oa->write_character(to_char_type(0x1B));
15935 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15936 }
15937 }
15938 else
15939 {
15940 // The conversions below encode the sign in the first
15941 // byte, and the value is converted to a positive number.
15942 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15943 if (j.m_data.m_value.number_integer >= -24)
15944 {
15945 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15946 }
15947 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15948 {
15949 oa->write_character(to_char_type(0x38));
15950 write_number(static_cast<std::uint8_t>(positive_number));
15951 }
15952 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15953 {
15954 oa->write_character(to_char_type(0x39));
15955 write_number(static_cast<std::uint16_t>(positive_number));
15956 }
15957 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15958 {
15959 oa->write_character(to_char_type(0x3A));
15960 write_number(static_cast<std::uint32_t>(positive_number));
15961 }
15962 else
15963 {
15964 oa->write_character(to_char_type(0x3B));
15965 write_number(static_cast<std::uint64_t>(positive_number));
15966 }
15967 }
15968 break;
15969 }
15970
15972 {
15973 if (j.m_data.m_value.number_unsigned <= 0x17)
15974 {
15975 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15976 }
15977 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15978 {
15979 oa->write_character(to_char_type(0x18));
15980 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15981 }
15982 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15983 {
15984 oa->write_character(to_char_type(0x19));
15985 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15986 }
15987 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15988 {
15989 oa->write_character(to_char_type(0x1A));
15990 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15991 }
15992 else
15993 {
15994 oa->write_character(to_char_type(0x1B));
15995 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15996 }
15997 break;
15998 }
15999
16001 {
16002 if (std::isnan(j.m_data.m_value.number_float))
16003 {
16004 // NaN is 0xf97e00 in CBOR
16005 oa->write_character(to_char_type(0xF9));
16006 oa->write_character(to_char_type(0x7E));
16007 oa->write_character(to_char_type(0x00));
16008 }
16009 else if (std::isinf(j.m_data.m_value.number_float))
16010 {
16011 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
16012 oa->write_character(to_char_type(0xf9));
16013 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
16014 oa->write_character(to_char_type(0x00));
16015 }
16016 else
16017 {
16018 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
16019 }
16020 break;
16021 }
16022
16023 case value_t::string:
16024 {
16025 // step 1: write control byte and the string length
16026 const auto N = j.m_data.m_value.string->size();
16027 if (N <= 0x17)
16028 {
16029 write_number(static_cast<std::uint8_t>(0x60 + N));
16030 }
16031 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16032 {
16033 oa->write_character(to_char_type(0x78));
16034 write_number(static_cast<std::uint8_t>(N));
16035 }
16036 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16037 {
16038 oa->write_character(to_char_type(0x79));
16039 write_number(static_cast<std::uint16_t>(N));
16040 }
16041 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16042 {
16043 oa->write_character(to_char_type(0x7A));
16044 write_number(static_cast<std::uint32_t>(N));
16045 }
16046 // LCOV_EXCL_START
16047 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16048 {
16049 oa->write_character(to_char_type(0x7B));
16050 write_number(static_cast<std::uint64_t>(N));
16051 }
16052 // LCOV_EXCL_STOP
16053
16054 // step 2: write the string
16055 oa->write_characters(
16056 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16057 j.m_data.m_value.string->size());
16058 break;
16059 }
16060
16061 case value_t::array:
16062 {
16063 // step 1: write control byte and the array size
16064 const auto N = j.m_data.m_value.array->size();
16065 if (N <= 0x17)
16066 {
16067 write_number(static_cast<std::uint8_t>(0x80 + N));
16068 }
16069 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16070 {
16071 oa->write_character(to_char_type(0x98));
16072 write_number(static_cast<std::uint8_t>(N));
16073 }
16074 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16075 {
16076 oa->write_character(to_char_type(0x99));
16077 write_number(static_cast<std::uint16_t>(N));
16078 }
16079 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16080 {
16081 oa->write_character(to_char_type(0x9A));
16082 write_number(static_cast<std::uint32_t>(N));
16083 }
16084 // LCOV_EXCL_START
16085 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16086 {
16087 oa->write_character(to_char_type(0x9B));
16088 write_number(static_cast<std::uint64_t>(N));
16089 }
16090 // LCOV_EXCL_STOP
16091
16092 // step 2: write each element
16093 for (const auto& el : *j.m_data.m_value.array)
16094 {
16095 write_cbor(el);
16096 }
16097 break;
16098 }
16099
16100 case value_t::binary:
16101 {
16102 if (j.m_data.m_value.binary->has_subtype())
16103 {
16104 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16105 {
16106 write_number(static_cast<std::uint8_t>(0xd8));
16107 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16108 }
16109 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16110 {
16111 write_number(static_cast<std::uint8_t>(0xd9));
16112 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16113 }
16114 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16115 {
16116 write_number(static_cast<std::uint8_t>(0xda));
16117 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16118 }
16119 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16120 {
16121 write_number(static_cast<std::uint8_t>(0xdb));
16122 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16123 }
16124 }
16125
16126 // step 1: write control byte and the binary array size
16127 const auto N = j.m_data.m_value.binary->size();
16128 if (N <= 0x17)
16129 {
16130 write_number(static_cast<std::uint8_t>(0x40 + N));
16131 }
16132 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16133 {
16134 oa->write_character(to_char_type(0x58));
16135 write_number(static_cast<std::uint8_t>(N));
16136 }
16137 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16138 {
16139 oa->write_character(to_char_type(0x59));
16140 write_number(static_cast<std::uint16_t>(N));
16141 }
16142 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16143 {
16144 oa->write_character(to_char_type(0x5A));
16145 write_number(static_cast<std::uint32_t>(N));
16146 }
16147 // LCOV_EXCL_START
16148 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16149 {
16150 oa->write_character(to_char_type(0x5B));
16151 write_number(static_cast<std::uint64_t>(N));
16152 }
16153 // LCOV_EXCL_STOP
16154
16155 // step 2: write each element
16156 oa->write_characters(
16157 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16158 N);
16159
16160 break;
16161 }
16162
16163 case value_t::object:
16164 {
16165 // step 1: write control byte and the object size
16166 const auto N = j.m_data.m_value.object->size();
16167 if (N <= 0x17)
16168 {
16169 write_number(static_cast<std::uint8_t>(0xA0 + N));
16170 }
16171 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16172 {
16173 oa->write_character(to_char_type(0xB8));
16174 write_number(static_cast<std::uint8_t>(N));
16175 }
16176 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16177 {
16178 oa->write_character(to_char_type(0xB9));
16179 write_number(static_cast<std::uint16_t>(N));
16180 }
16181 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16182 {
16183 oa->write_character(to_char_type(0xBA));
16184 write_number(static_cast<std::uint32_t>(N));
16185 }
16186 // LCOV_EXCL_START
16187 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16188 {
16189 oa->write_character(to_char_type(0xBB));
16190 write_number(static_cast<std::uint64_t>(N));
16191 }
16192 // LCOV_EXCL_STOP
16193
16194 // step 2: write each element
16195 for (const auto& el : *j.m_data.m_value.object)
16196 {
16197 write_cbor(el.first);
16198 write_cbor(el.second);
16199 }
16200 break;
16201 }
16202
16203 case value_t::discarded:
16204 default:
16205 break;
16206 }
16207 }
16208
16212 void write_msgpack(const BasicJsonType& j)
16213 {
16214 switch (j.type())
16215 {
16216 case value_t::null: // nil
16217 {
16218 oa->write_character(to_char_type(0xC0));
16219 break;
16220 }
16221
16222 case value_t::boolean: // true and false
16223 {
16224 oa->write_character(j.m_data.m_value.boolean
16225 ? to_char_type(0xC3)
16226 : to_char_type(0xC2));
16227 break;
16228 }
16229
16231 {
16232 if (j.m_data.m_value.number_integer >= 0)
16233 {
16234 // MessagePack does not differentiate between positive
16235 // signed integers and unsigned integers. Therefore, we used
16236 // the code from the value_t::number_unsigned case here.
16237 if (j.m_data.m_value.number_unsigned < 128)
16238 {
16239 // positive fixnum
16240 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16241 }
16242 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16243 {
16244 // uint 8
16245 oa->write_character(to_char_type(0xCC));
16246 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16247 }
16248 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16249 {
16250 // uint 16
16251 oa->write_character(to_char_type(0xCD));
16252 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16253 }
16254 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16255 {
16256 // uint 32
16257 oa->write_character(to_char_type(0xCE));
16258 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16259 }
16260 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16261 {
16262 // uint 64
16263 oa->write_character(to_char_type(0xCF));
16264 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16265 }
16266 }
16267 else
16268 {
16269 if (j.m_data.m_value.number_integer >= -32)
16270 {
16271 // negative fixnum
16272 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16273 }
16274 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16275 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16276 {
16277 // int 8
16278 oa->write_character(to_char_type(0xD0));
16279 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16280 }
16281 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16282 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16283 {
16284 // int 16
16285 oa->write_character(to_char_type(0xD1));
16286 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16287 }
16288 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16289 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16290 {
16291 // int 32
16292 oa->write_character(to_char_type(0xD2));
16293 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16294 }
16295 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16296 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16297 {
16298 // int 64
16299 oa->write_character(to_char_type(0xD3));
16300 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16301 }
16302 }
16303 break;
16304 }
16305
16307 {
16308 if (j.m_data.m_value.number_unsigned < 128)
16309 {
16310 // positive fixnum
16311 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16312 }
16313 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16314 {
16315 // uint 8
16316 oa->write_character(to_char_type(0xCC));
16317 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16318 }
16319 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16320 {
16321 // uint 16
16322 oa->write_character(to_char_type(0xCD));
16323 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16324 }
16325 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16326 {
16327 // uint 32
16328 oa->write_character(to_char_type(0xCE));
16329 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16330 }
16331 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16332 {
16333 // uint 64
16334 oa->write_character(to_char_type(0xCF));
16335 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16336 }
16337 break;
16338 }
16339
16341 {
16342 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16343 break;
16344 }
16345
16346 case value_t::string:
16347 {
16348 // step 1: write control byte and the string length
16349 const auto N = j.m_data.m_value.string->size();
16350 if (N <= 31)
16351 {
16352 // fixstr
16353 write_number(static_cast<std::uint8_t>(0xA0 | N));
16354 }
16355 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16356 {
16357 // str 8
16358 oa->write_character(to_char_type(0xD9));
16359 write_number(static_cast<std::uint8_t>(N));
16360 }
16361 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16362 {
16363 // str 16
16364 oa->write_character(to_char_type(0xDA));
16365 write_number(static_cast<std::uint16_t>(N));
16366 }
16367 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16368 {
16369 // str 32
16370 oa->write_character(to_char_type(0xDB));
16371 write_number(static_cast<std::uint32_t>(N));
16372 }
16373
16374 // step 2: write the string
16375 oa->write_characters(
16376 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16377 j.m_data.m_value.string->size());
16378 break;
16379 }
16380
16381 case value_t::array:
16382 {
16383 // step 1: write control byte and the array size
16384 const auto N = j.m_data.m_value.array->size();
16385 if (N <= 15)
16386 {
16387 // fixarray
16388 write_number(static_cast<std::uint8_t>(0x90 | N));
16389 }
16390 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16391 {
16392 // array 16
16393 oa->write_character(to_char_type(0xDC));
16394 write_number(static_cast<std::uint16_t>(N));
16395 }
16396 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16397 {
16398 // array 32
16399 oa->write_character(to_char_type(0xDD));
16400 write_number(static_cast<std::uint32_t>(N));
16401 }
16402
16403 // step 2: write each element
16404 for (const auto& el : *j.m_data.m_value.array)
16405 {
16406 write_msgpack(el);
16407 }
16408 break;
16409 }
16410
16411 case value_t::binary:
16412 {
16413 // step 0: determine if the binary type has a set subtype to
16414 // determine whether to use the ext or fixext types
16415 const bool use_ext = j.m_data.m_value.binary->has_subtype();
16416
16417 // step 1: write control byte and the byte string length
16418 const auto N = j.m_data.m_value.binary->size();
16419 if (N <= (std::numeric_limits<std::uint8_t>::max)())
16420 {
16421 std::uint8_t output_type{};
16422 bool fixed = true;
16423 if (use_ext)
16424 {
16425 switch (N)
16426 {
16427 case 1:
16428 output_type = 0xD4; // fixext 1
16429 break;
16430 case 2:
16431 output_type = 0xD5; // fixext 2
16432 break;
16433 case 4:
16434 output_type = 0xD6; // fixext 4
16435 break;
16436 case 8:
16437 output_type = 0xD7; // fixext 8
16438 break;
16439 case 16:
16440 output_type = 0xD8; // fixext 16
16441 break;
16442 default:
16443 output_type = 0xC7; // ext 8
16444 fixed = false;
16445 break;
16446 }
16447
16448 }
16449 else
16450 {
16451 output_type = 0xC4; // bin 8
16452 fixed = false;
16453 }
16454
16455 oa->write_character(to_char_type(output_type));
16456 if (!fixed)
16457 {
16458 write_number(static_cast<std::uint8_t>(N));
16459 }
16460 }
16461 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16462 {
16463 const std::uint8_t output_type = use_ext
16464 ? 0xC8 // ext 16
16465 : 0xC5; // bin 16
16466
16467 oa->write_character(to_char_type(output_type));
16468 write_number(static_cast<std::uint16_t>(N));
16469 }
16470 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16471 {
16472 const std::uint8_t output_type = use_ext
16473 ? 0xC9 // ext 32
16474 : 0xC6; // bin 32
16475
16476 oa->write_character(to_char_type(output_type));
16477 write_number(static_cast<std::uint32_t>(N));
16478 }
16479
16480 // step 1.5: if this is an ext type, write the subtype
16481 if (use_ext)
16482 {
16483 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16484 }
16485
16486 // step 2: write the byte string
16487 oa->write_characters(
16488 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16489 N);
16490
16491 break;
16492 }
16493
16494 case value_t::object:
16495 {
16496 // step 1: write control byte and the object size
16497 const auto N = j.m_data.m_value.object->size();
16498 if (N <= 15)
16499 {
16500 // fixmap
16501 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16502 }
16503 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16504 {
16505 // map 16
16506 oa->write_character(to_char_type(0xDE));
16507 write_number(static_cast<std::uint16_t>(N));
16508 }
16509 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16510 {
16511 // map 32
16512 oa->write_character(to_char_type(0xDF));
16513 write_number(static_cast<std::uint32_t>(N));
16514 }
16515
16516 // step 2: write each element
16517 for (const auto& el : *j.m_data.m_value.object)
16518 {
16519 write_msgpack(el.first);
16520 write_msgpack(el.second);
16521 }
16522 break;
16523 }
16524
16525 case value_t::discarded:
16526 default:
16527 break;
16528 }
16529 }
16530
16539 void write_ubjson(const BasicJsonType& j, const bool use_count,
16540 const bool use_type, const bool add_prefix = true,
16541 const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16542 {
16543 const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16544
16545 switch (j.type())
16546 {
16547 case value_t::null:
16548 {
16549 if (add_prefix)
16550 {
16551 oa->write_character(to_char_type('Z'));
16552 }
16553 break;
16554 }
16555
16556 case value_t::boolean:
16557 {
16558 if (add_prefix)
16559 {
16560 oa->write_character(j.m_data.m_value.boolean
16561 ? to_char_type('T')
16562 : to_char_type('F'));
16563 }
16564 break;
16565 }
16566
16568 {
16569 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16570 break;
16571 }
16572
16574 {
16575 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16576 break;
16577 }
16578
16580 {
16581 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16582 break;
16583 }
16584
16585 case value_t::string:
16586 {
16587 if (add_prefix)
16588 {
16589 oa->write_character(to_char_type('S'));
16590 }
16591 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16592 oa->write_characters(
16593 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16594 j.m_data.m_value.string->size());
16595 break;
16596 }
16597
16598 case value_t::array:
16599 {
16600 if (add_prefix)
16601 {
16602 oa->write_character(to_char_type('['));
16603 }
16604
16605 bool prefix_required = true;
16606 if (use_type && !j.m_data.m_value.array->empty())
16607 {
16608 JSON_ASSERT(use_count);
16609 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16610 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16611 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16612 {
16613 return ubjson_prefix(v, use_bjdata) == first_prefix;
16614 });
16615
16616 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16617
16618 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16619 {
16620 prefix_required = false;
16621 oa->write_character(to_char_type('$'));
16622 oa->write_character(first_prefix);
16623 }
16624 }
16625
16626 if (use_count)
16627 {
16628 oa->write_character(to_char_type('#'));
16629 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16630 }
16631
16632 for (const auto& el : *j.m_data.m_value.array)
16633 {
16634 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16635 }
16636
16637 if (!use_count)
16638 {
16639 oa->write_character(to_char_type(']'));
16640 }
16641
16642 break;
16643 }
16644
16645 case value_t::binary:
16646 {
16647 if (add_prefix)
16648 {
16649 oa->write_character(to_char_type('['));
16650 }
16651
16652 if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16653 {
16654 JSON_ASSERT(use_count);
16655 oa->write_character(to_char_type('$'));
16656 oa->write_character(bjdata_draft3 ? 'B' : 'U');
16657 }
16658
16659 if (use_count)
16660 {
16661 oa->write_character(to_char_type('#'));
16662 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16663 }
16664
16665 if (use_type)
16666 {
16667 oa->write_characters(
16668 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16669 j.m_data.m_value.binary->size());
16670 }
16671 else
16672 {
16673 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16674 {
16675 oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16676 oa->write_character(j.m_data.m_value.binary->data()[i]);
16677 }
16678 }
16679
16680 if (!use_count)
16681 {
16682 oa->write_character(to_char_type(']'));
16683 }
16684
16685 break;
16686 }
16687
16688 case value_t::object:
16689 {
16690 if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
16691 {
16692 if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type, bjdata_version)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
16693 {
16694 break;
16695 }
16696 }
16697
16698 if (add_prefix)
16699 {
16700 oa->write_character(to_char_type('{'));
16701 }
16702
16703 bool prefix_required = true;
16704 if (use_type && !j.m_data.m_value.object->empty())
16705 {
16706 JSON_ASSERT(use_count);
16707 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16708 const bool same_prefix = std::all_of(j.begin(), j.end(),
16709 [this, first_prefix, use_bjdata](const BasicJsonType & v)
16710 {
16711 return ubjson_prefix(v, use_bjdata) == first_prefix;
16712 });
16713
16714 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16715
16716 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16717 {
16718 prefix_required = false;
16719 oa->write_character(to_char_type('$'));
16720 oa->write_character(first_prefix);
16721 }
16722 }
16723
16724 if (use_count)
16725 {
16726 oa->write_character(to_char_type('#'));
16727 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16728 }
16729
16730 for (const auto& el : *j.m_data.m_value.object)
16731 {
16732 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16733 oa->write_characters(
16734 reinterpret_cast<const CharType*>(el.first.c_str()),
16735 el.first.size());
16736 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16737 }
16738
16739 if (!use_count)
16740 {
16741 oa->write_character(to_char_type('}'));
16742 }
16743
16744 break;
16745 }
16746
16747 case value_t::discarded:
16748 default:
16749 break;
16750 }
16751 }
16752
16753 private:
16755 // BSON //
16757
16762 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16763 {
16764 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16765 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16766 {
16767 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16768 }
16769
16770 static_cast<void>(j);
16771 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16772 }
16773
16777 void write_bson_entry_header(const string_t& name,
16778 const std::uint8_t element_type)
16779 {
16780 oa->write_character(to_char_type(element_type)); // boolean
16781 oa->write_characters(
16782 reinterpret_cast<const CharType*>(name.c_str()),
16783 name.size() + 1u);
16784 }
16785
16789 void write_bson_boolean(const string_t& name,
16790 const bool value)
16791 {
16792 write_bson_entry_header(name, 0x08);
16793 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16794 }
16795
16799 void write_bson_double(const string_t& name,
16800 const double value)
16801 {
16802 write_bson_entry_header(name, 0x01);
16803 write_number<double>(value, true);
16804 }
16805
16809 static std::size_t calc_bson_string_size(const string_t& value)
16810 {
16811 return sizeof(std::int32_t) + value.size() + 1ul;
16812 }
16813
16817 void write_bson_string(const string_t& name,
16818 const string_t& value)
16819 {
16820 write_bson_entry_header(name, 0x02);
16821
16822 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16823 oa->write_characters(
16824 reinterpret_cast<const CharType*>(value.c_str()),
16825 value.size() + 1);
16826 }
16827
16831 void write_bson_null(const string_t& name)
16832 {
16833 write_bson_entry_header(name, 0x0A);
16834 }
16835
16839 static std::size_t calc_bson_integer_size(const std::int64_t value)
16840 {
16841 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16842 ? sizeof(std::int32_t)
16843 : sizeof(std::int64_t);
16844 }
16845
16849 void write_bson_integer(const string_t& name,
16850 const std::int64_t value)
16851 {
16852 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16853 {
16854 write_bson_entry_header(name, 0x10); // int32
16855 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16856 }
16857 else
16858 {
16859 write_bson_entry_header(name, 0x12); // int64
16860 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16861 }
16862 }
16863
16867 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16868 {
16869 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16870 ? sizeof(std::int32_t)
16871 : sizeof(std::int64_t);
16872 }
16873
16877 void write_bson_unsigned(const string_t& name,
16878 const BasicJsonType& j)
16879 {
16880 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16881 {
16882 write_bson_entry_header(name, 0x10 /* int32 */);
16883 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16884 }
16885 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16886 {
16887 write_bson_entry_header(name, 0x12 /* int64 */);
16888 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16889 }
16890 else
16891 {
16892 write_bson_entry_header(name, 0x11 /* uint64 */);
16893 write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16894 }
16895 }
16896
16900 void write_bson_object_entry(const string_t& name,
16901 const typename BasicJsonType::object_t& value)
16902 {
16903 write_bson_entry_header(name, 0x03); // object
16904 write_bson_object(value);
16905 }
16906
16910 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16911 {
16912 std::size_t array_index = 0ul;
16913
16914 const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
16915 {
16916 return result + calc_bson_element_size(std::to_string(array_index++), el);
16917 });
16918
16919 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16920 }
16921
16925 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16926 {
16927 return sizeof(std::int32_t) + value.size() + 1ul;
16928 }
16929
16933 void write_bson_array(const string_t& name,
16934 const typename BasicJsonType::array_t& value)
16935 {
16936 write_bson_entry_header(name, 0x04); // array
16937 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16938
16939 std::size_t array_index = 0ul;
16940
16941 for (const auto& el : value)
16942 {
16943 write_bson_element(std::to_string(array_index++), el);
16944 }
16945
16946 oa->write_character(to_char_type(0x00));
16947 }
16948
16952 void write_bson_binary(const string_t& name,
16953 const binary_t& value)
16954 {
16955 write_bson_entry_header(name, 0x05);
16956
16957 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16958 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16959
16960 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16961 }
16962
16967 static std::size_t calc_bson_element_size(const string_t& name,
16968 const BasicJsonType& j)
16969 {
16970 const auto header_size = calc_bson_entry_header_size(name, j);
16971 switch (j.type())
16972 {
16973 case value_t::object:
16974 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16975
16976 case value_t::array:
16977 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16978
16979 case value_t::binary:
16980 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16981
16982 case value_t::boolean:
16983 return header_size + 1ul;
16984
16985 case value_t::number_float:
16986 return header_size + 8ul;
16987
16988 case value_t::number_integer:
16989 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16990
16991 case value_t::number_unsigned:
16992 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16993
16994 case value_t::string:
16995 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16996
16997 case value_t::null:
16998 return header_size + 0ul;
16999
17000 // LCOV_EXCL_START
17001 case value_t::discarded:
17002 default:
17003 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17004 return 0ul;
17005 // LCOV_EXCL_STOP
17006 }
17007 }
17008
17015 void write_bson_element(const string_t& name,
17016 const BasicJsonType& j)
17017 {
17018 switch (j.type())
17019 {
17020 case value_t::object:
17021 return write_bson_object_entry(name, *j.m_data.m_value.object);
17022
17023 case value_t::array:
17024 return write_bson_array(name, *j.m_data.m_value.array);
17025
17026 case value_t::binary:
17027 return write_bson_binary(name, *j.m_data.m_value.binary);
17028
17029 case value_t::boolean:
17030 return write_bson_boolean(name, j.m_data.m_value.boolean);
17031
17032 case value_t::number_float:
17033 return write_bson_double(name, j.m_data.m_value.number_float);
17034
17035 case value_t::number_integer:
17036 return write_bson_integer(name, j.m_data.m_value.number_integer);
17037
17038 case value_t::number_unsigned:
17039 return write_bson_unsigned(name, j);
17040
17041 case value_t::string:
17042 return write_bson_string(name, *j.m_data.m_value.string);
17043
17044 case value_t::null:
17045 return write_bson_null(name);
17046
17047 // LCOV_EXCL_START
17048 case value_t::discarded:
17049 default:
17050 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
17051 return;
17052 // LCOV_EXCL_STOP
17053 }
17054 }
17055
17062 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17063 {
17064 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17065 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17066 {
17067 return result += calc_bson_element_size(el.first, el.second);
17068 });
17069
17070 return sizeof(std::int32_t) + document_size + 1ul;
17071 }
17072
17077 void write_bson_object(const typename BasicJsonType::object_t& value)
17078 {
17079 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17080
17081 for (const auto& el : value)
17082 {
17083 write_bson_element(el.first, el.second);
17084 }
17085
17086 oa->write_character(to_char_type(0x00));
17087 }
17088
17090 // CBOR //
17092
17093 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17094 {
17095 return to_char_type(0xFA); // Single-Precision Float
17096 }
17097
17098 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17099 {
17100 return to_char_type(0xFB); // Double-Precision Float
17101 }
17102
17104 // MsgPack //
17106
17107 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17108 {
17109 return to_char_type(0xCA); // float 32
17110 }
17111
17112 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17113 {
17114 return to_char_type(0xCB); // float 64
17115 }
17116
17118 // UBJSON //
17120
17121 // UBJSON: write number (floating point)
17122 template<typename NumberType, typename std::enable_if<
17123 std::is_floating_point<NumberType>::value, int>::type = 0>
17124 void write_number_with_ubjson_prefix(const NumberType n,
17125 const bool add_prefix,
17126 const bool use_bjdata)
17127 {
17128 if (add_prefix)
17129 {
17130 oa->write_character(get_ubjson_float_prefix(n));
17131 }
17132 write_number(n, use_bjdata);
17133 }
17134
17135 // UBJSON: write number (unsigned integer)
17136 template<typename NumberType, typename std::enable_if<
17137 std::is_unsigned<NumberType>::value, int>::type = 0>
17138 void write_number_with_ubjson_prefix(const NumberType n,
17139 const bool add_prefix,
17140 const bool use_bjdata)
17141 {
17142 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17143 {
17144 if (add_prefix)
17145 {
17146 oa->write_character(to_char_type('i')); // int8
17147 }
17148 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17149 }
17150 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17151 {
17152 if (add_prefix)
17153 {
17154 oa->write_character(to_char_type('U')); // uint8
17155 }
17156 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17157 }
17158 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17159 {
17160 if (add_prefix)
17161 {
17162 oa->write_character(to_char_type('I')); // int16
17163 }
17164 write_number(static_cast<std::int16_t>(n), use_bjdata);
17165 }
17166 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17167 {
17168 if (add_prefix)
17169 {
17170 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17171 }
17172 write_number(static_cast<std::uint16_t>(n), use_bjdata);
17173 }
17174 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17175 {
17176 if (add_prefix)
17177 {
17178 oa->write_character(to_char_type('l')); // int32
17179 }
17180 write_number(static_cast<std::int32_t>(n), use_bjdata);
17181 }
17182 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17183 {
17184 if (add_prefix)
17185 {
17186 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17187 }
17188 write_number(static_cast<std::uint32_t>(n), use_bjdata);
17189 }
17190 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17191 {
17192 if (add_prefix)
17193 {
17194 oa->write_character(to_char_type('L')); // int64
17195 }
17196 write_number(static_cast<std::int64_t>(n), use_bjdata);
17197 }
17198 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17199 {
17200 if (add_prefix)
17201 {
17202 oa->write_character(to_char_type('M')); // uint64 - bjdata only
17203 }
17204 write_number(static_cast<std::uint64_t>(n), use_bjdata);
17205 }
17206 else
17207 {
17208 if (add_prefix)
17209 {
17210 oa->write_character(to_char_type('H')); // high-precision number
17211 }
17212
17213 const auto number = BasicJsonType(n).dump();
17214 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17215 for (std::size_t i = 0; i < number.size(); ++i)
17216 {
17217 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17218 }
17219 }
17220 }
17221
17222 // UBJSON: write number (signed integer)
17223 template < typename NumberType, typename std::enable_if <
17224 std::is_signed<NumberType>::value&&
17225 !std::is_floating_point<NumberType>::value, int >::type = 0 >
17226 void write_number_with_ubjson_prefix(const NumberType n,
17227 const bool add_prefix,
17228 const bool use_bjdata)
17229 {
17230 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17231 {
17232 if (add_prefix)
17233 {
17234 oa->write_character(to_char_type('i')); // int8
17235 }
17236 write_number(static_cast<std::int8_t>(n), use_bjdata);
17237 }
17238 else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
17239 {
17240 if (add_prefix)
17241 {
17242 oa->write_character(to_char_type('U')); // uint8
17243 }
17244 write_number(static_cast<std::uint8_t>(n), use_bjdata);
17245 }
17246 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17247 {
17248 if (add_prefix)
17249 {
17250 oa->write_character(to_char_type('I')); // int16
17251 }
17252 write_number(static_cast<std::int16_t>(n), use_bjdata);
17253 }
17254 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
17255 {
17256 if (add_prefix)
17257 {
17258 oa->write_character(to_char_type('u')); // uint16 - bjdata only
17259 }
17260 write_number(static_cast<uint16_t>(n), use_bjdata);
17261 }
17262 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17263 {
17264 if (add_prefix)
17265 {
17266 oa->write_character(to_char_type('l')); // int32
17267 }
17268 write_number(static_cast<std::int32_t>(n), use_bjdata);
17269 }
17270 else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
17271 {
17272 if (add_prefix)
17273 {
17274 oa->write_character(to_char_type('m')); // uint32 - bjdata only
17275 }
17276 write_number(static_cast<uint32_t>(n), use_bjdata);
17277 }
17278 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17279 {
17280 if (add_prefix)
17281 {
17282 oa->write_character(to_char_type('L')); // int64
17283 }
17284 write_number(static_cast<std::int64_t>(n), use_bjdata);
17285 }
17286 // LCOV_EXCL_START
17287 else
17288 {
17289 if (add_prefix)
17290 {
17291 oa->write_character(to_char_type('H')); // high-precision number
17292 }
17293
17294 const auto number = BasicJsonType(n).dump();
17295 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17296 for (std::size_t i = 0; i < number.size(); ++i)
17297 {
17298 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17299 }
17300 }
17301 // LCOV_EXCL_STOP
17302 }
17303
17307 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17308 {
17309 switch (j.type())
17310 {
17311 case value_t::null:
17312 return 'Z';
17313
17314 case value_t::boolean:
17315 return j.m_data.m_value.boolean ? 'T' : 'F';
17316
17317 case value_t::number_integer:
17318 {
17319 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
17320 {
17321 return 'i';
17322 }
17323 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
17324 {
17325 return 'U';
17326 }
17327 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
17328 {
17329 return 'I';
17330 }
17331 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
17332 {
17333 return 'u';
17334 }
17335 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
17336 {
17337 return 'l';
17338 }
17339 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
17340 {
17341 return 'm';
17342 }
17343 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
17344 {
17345 return 'L';
17346 }
17347 // anything else is treated as a high-precision number
17348 return 'H'; // LCOV_EXCL_LINE
17349 }
17350
17351 case value_t::number_unsigned:
17352 {
17353 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17354 {
17355 return 'i';
17356 }
17357 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17358 {
17359 return 'U';
17360 }
17361 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17362 {
17363 return 'I';
17364 }
17365 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17366 {
17367 return 'u';
17368 }
17369 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17370 {
17371 return 'l';
17372 }
17373 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17374 {
17375 return 'm';
17376 }
17377 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17378 {
17379 return 'L';
17380 }
17381 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17382 {
17383 return 'M';
17384 }
17385 // anything else is treated as a high-precision number
17386 return 'H'; // LCOV_EXCL_LINE
17387 }
17388
17389 case value_t::number_float:
17390 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17391
17392 case value_t::string:
17393 return 'S';
17394
17395 case value_t::array: // fallthrough
17396 case value_t::binary:
17397 return '[';
17398
17399 case value_t::object:
17400 return '{';
17401
17402 case value_t::discarded:
17403 default: // discarded values
17404 return 'N';
17405 }
17406 }
17407
17408 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17409 {
17410 return 'd'; // float 32
17411 }
17412
17413 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17414 {
17415 return 'D'; // float 64
17416 }
17417
17421 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17422 {
17423 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
17424 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17425 {"char", 'C'}, {"byte", 'B'}
17426 };
17427
17428 string_t key = "_ArrayType_";
17429 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17430 if (it == bjdtype.end())
17431 {
17432 return true;
17433 }
17434 CharType dtype = it->second;
17435
17436 key = "_ArraySize_";
17437 std::size_t len = (value.at(key).empty() ? 0 : 1);
17438 for (const auto& el : value.at(key))
17439 {
17440 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17441 }
17442
17443 key = "_ArrayData_";
17444 if (value.at(key).size() != len)
17445 {
17446 return true;
17447 }
17448
17449 oa->write_character('[');
17450 oa->write_character('$');
17451 oa->write_character(dtype);
17452 oa->write_character('#');
17453
17454 key = "_ArraySize_";
17455 write_ubjson(value.at(key), use_count, use_type, true, true, bjdata_version);
17456
17457 key = "_ArrayData_";
17458 if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17459 {
17460 for (const auto& el : value.at(key))
17461 {
17462 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17463 }
17464 }
17465 else if (dtype == 'i')
17466 {
17467 for (const auto& el : value.at(key))
17468 {
17469 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17470 }
17471 }
17472 else if (dtype == 'u')
17473 {
17474 for (const auto& el : value.at(key))
17475 {
17476 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17477 }
17478 }
17479 else if (dtype == 'I')
17480 {
17481 for (const auto& el : value.at(key))
17482 {
17483 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17484 }
17485 }
17486 else if (dtype == 'm')
17487 {
17488 for (const auto& el : value.at(key))
17489 {
17490 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17491 }
17492 }
17493 else if (dtype == 'l')
17494 {
17495 for (const auto& el : value.at(key))
17496 {
17497 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17498 }
17499 }
17500 else if (dtype == 'M')
17501 {
17502 for (const auto& el : value.at(key))
17503 {
17504 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17505 }
17506 }
17507 else if (dtype == 'L')
17508 {
17509 for (const auto& el : value.at(key))
17510 {
17511 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17512 }
17513 }
17514 else if (dtype == 'd')
17515 {
17516 for (const auto& el : value.at(key))
17517 {
17518 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17519 }
17520 }
17521 else if (dtype == 'D')
17522 {
17523 for (const auto& el : value.at(key))
17524 {
17525 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17526 }
17527 }
17528 return false;
17529 }
17530
17532 // Utility functions //
17534
17535 /*
17536 @brief write a number to output input
17537 @param[in] n number of type @a NumberType
17538 @param[in] OutputIsLittleEndian Set to true if output data is
17539 required to be little endian
17540 @tparam NumberType the type of the number
17541
17542 @note This function needs to respect the system's endianness, because bytes
17543 in CBOR, MessagePack, and UBJSON are stored in network order (big
17544 endian) and therefore need reordering on little endian systems.
17545 On the other hand, BSON and BJData use little endian and should reorder
17546 on big endian systems.
17547 */
17548 template<typename NumberType>
17549 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17550 {
17551 // step 1: write the number to an array of length NumberType
17552 std::array<CharType, sizeof(NumberType)> vec{};
17553 std::memcpy(vec.data(), &n, sizeof(NumberType));
17554
17555 // step 2: write the array to output (with possible reordering)
17556 if (is_little_endian != OutputIsLittleEndian)
17557 {
17558 // reverse byte order prior to conversion if necessary
17559 std::reverse(vec.begin(), vec.end());
17560 }
17561
17562 oa->write_characters(vec.data(), sizeof(NumberType));
17563 }
17564
17565 void write_compact_float(const number_float_t n, detail::input_format_t format)
17566 {
17567#ifdef __GNUC__
17568#pragma GCC diagnostic push
17569#pragma GCC diagnostic ignored "-Wfloat-equal"
17570#endif
17571 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17572 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17573 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
17574 {
17575 oa->write_character(format == detail::input_format_t::cbor
17576 ? get_cbor_float_prefix(static_cast<float>(n))
17577 : get_msgpack_float_prefix(static_cast<float>(n)));
17578 write_number(static_cast<float>(n));
17579 }
17580 else
17581 {
17582 oa->write_character(format == detail::input_format_t::cbor
17583 ? get_cbor_float_prefix(n)
17584 : get_msgpack_float_prefix(n));
17585 write_number(n);
17586 }
17587#ifdef __GNUC__
17588#pragma GCC diagnostic pop
17589#endif
17590 }
17591
17592 public:
17593 // The following to_char_type functions are implement the conversion
17594 // between uint8_t and CharType. In case CharType is not unsigned,
17595 // such a conversion is required to allow values greater than 128.
17596 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17597 template < typename C = CharType,
17598 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17599 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17600 {
17601 return *reinterpret_cast<char*>(&x);
17602 }
17603
17604 template < typename C = CharType,
17605 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17606 static CharType to_char_type(std::uint8_t x) noexcept
17607 {
17608 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17609 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17610 CharType result;
17611 std::memcpy(&result, &x, sizeof(x));
17612 return result;
17613 }
17614
17615 template<typename C = CharType,
17617 static constexpr CharType to_char_type(std::uint8_t x) noexcept
17618 {
17619 return x;
17620 }
17621
17622 template < typename InputCharType, typename C = CharType,
17623 enable_if_t <
17624 std::is_signed<C>::value &&
17625 std::is_signed<char>::value &&
17626 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17627 > * = nullptr >
17628 static constexpr CharType to_char_type(InputCharType x) noexcept
17629 {
17630 return x;
17631 }
17632
17633 private:
17635 const bool is_little_endian = little_endianness();
17636
17638 output_adapter_t<CharType> oa = nullptr;
17639};
17640
17641} // namespace detail
17643
17644// #include <nlohmann/detail/output/output_adapters.hpp>
17645
17646// #include <nlohmann/detail/output/serializer.hpp>
17647// __ _____ _____ _____
17648// __| | __| | | | JSON for Modern C++
17649// | | |__ | | | | | | version 3.12.0
17650// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17651//
17652// SPDX-FileCopyrightText: 2008 - 2009 Björn Hoehrmann <bjoern@hoehrmann.de>
17653// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17654// SPDX-License-Identifier: MIT
17655
17656
17657
17658#include <algorithm> // reverse, remove, fill, find, none_of
17659#include <array> // array
17660#include <clocale> // localeconv, lconv
17661#include <cmath> // labs, isfinite, isnan, signbit
17662#include <cstddef> // size_t, ptrdiff_t
17663#include <cstdint> // uint8_t
17664#include <cstdio> // snprintf
17665#include <limits> // numeric_limits
17666#include <string> // string, char_traits
17667#include <iomanip> // setfill, setw
17668#include <type_traits> // is_same
17669#include <utility> // move
17670
17671// #include <nlohmann/detail/conversions/to_chars.hpp>
17672// __ _____ _____ _____
17673// __| | __| | | | JSON for Modern C++
17674// | | |__ | | | | | | version 3.12.0
17675// |_____|_____|_____|_|___| https://github.com/nlohmann/json
17676//
17677// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17678// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17679// SPDX-License-Identifier: MIT
17680
17681
17682
17683#include <array> // array
17684#include <cmath> // signbit, isfinite
17685#include <cstdint> // intN_t, uintN_t
17686#include <cstring> // memcpy, memmove
17687#include <limits> // numeric_limits
17688#include <type_traits> // conditional
17689
17690// #include <nlohmann/detail/macro_scope.hpp>
17691
17692
17694namespace detail
17695{
17696
17716namespace dtoa_impl
17717{
17718
17719template<typename Target, typename Source>
17720Target reinterpret_bits(const Source source)
17721{
17722 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17723
17724 Target target;
17725 std::memcpy(&target, &source, sizeof(Source));
17726 return target;
17727}
17728
17729struct diyfp // f * 2^e
17730{
17731 static constexpr int kPrecision = 64; // = q
17732
17733 std::uint64_t f = 0;
17734 int e = 0;
17735
17736 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17737
17742 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17743 {
17744 JSON_ASSERT(x.e == y.e);
17745 JSON_ASSERT(x.f >= y.f);
17746
17747 return {x.f - y.f, x.e};
17748 }
17749
17754 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17755 {
17756 static_assert(kPrecision == 64, "internal error");
17757
17758 // Computes:
17759 // f = round((x.f * y.f) / 2^q)
17760 // e = x.e + y.e + q
17761
17762 // Emulate the 64-bit * 64-bit multiplication:
17763 //
17764 // p = u * v
17765 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17766 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17767 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17768 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17769 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17770 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17771 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17772 //
17773 // (Since Q might be larger than 2^32 - 1)
17774 //
17775 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17776 //
17777 // (Q_hi + H does not overflow a 64-bit int)
17778 //
17779 // = p_lo + 2^64 p_hi
17780
17781 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17782 const std::uint64_t u_hi = x.f >> 32u;
17783 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17784 const std::uint64_t v_hi = y.f >> 32u;
17785
17786 const std::uint64_t p0 = u_lo * v_lo;
17787 const std::uint64_t p1 = u_lo * v_hi;
17788 const std::uint64_t p2 = u_hi * v_lo;
17789 const std::uint64_t p3 = u_hi * v_hi;
17790
17791 const std::uint64_t p0_hi = p0 >> 32u;
17792 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17793 const std::uint64_t p1_hi = p1 >> 32u;
17794 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17795 const std::uint64_t p2_hi = p2 >> 32u;
17796
17797 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17798
17799 // The full product might now be computed as
17800 //
17801 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17802 // p_lo = p0_lo + (Q << 32)
17803 //
17804 // But in this particular case here, the full p_lo is not required.
17805 // Effectively, we only need to add the highest bit in p_lo to p_hi (and
17806 // Q_hi + 1 does not overflow).
17807
17808 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17809
17810 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17811
17812 return {h, x.e + y.e + 64};
17813 }
17814
17819 static diyfp normalize(diyfp x) noexcept
17820 {
17821 JSON_ASSERT(x.f != 0);
17822
17823 while ((x.f >> 63u) == 0)
17824 {
17825 x.f <<= 1u;
17826 x.e--;
17827 }
17828
17829 return x;
17830 }
17831
17836 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17837 {
17838 const int delta = x.e - target_exponent;
17839
17840 JSON_ASSERT(delta >= 0);
17841 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17842
17843 return {x.f << delta, target_exponent};
17844 }
17845};
17846
17853
17860template<typename FloatType>
17862{
17863 JSON_ASSERT(std::isfinite(value));
17864 JSON_ASSERT(value > 0);
17865
17866 // Convert the IEEE representation into a diyfp.
17867 //
17868 // If v is denormal:
17869 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17870 // If v is normalized:
17871 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17872
17873 static_assert(std::numeric_limits<FloatType>::is_iec559,
17874 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17875
17876 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17877 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17878 constexpr int kMinExp = 1 - kBias;
17879 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17880
17881 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17882
17883 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17884 const std::uint64_t E = bits >> (kPrecision - 1);
17885 const std::uint64_t F = bits & (kHiddenBit - 1);
17886
17887 const bool is_denormal = E == 0;
17888 const diyfp v = is_denormal
17889 ? diyfp(F, kMinExp)
17890 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17891
17892 // Compute the boundaries m- and m+ of the floating-point value
17893 // v = f * 2^e.
17894 //
17895 // Determine v- and v+, the floating-point predecessor and successor of v,
17896 // respectively.
17897 //
17898 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17899 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17900 //
17901 // v+ = v + 2^e
17902 //
17903 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17904 // between m- and m+ round to v, regardless of how the input rounding
17905 // algorithm breaks ties.
17906 //
17907 // ---+-------------+-------------+-------------+-------------+--- (A)
17908 // v- m- v m+ v+
17909 //
17910 // -----------------+------+------+-------------+-------------+--- (B)
17911 // v- m- v m+ v+
17912
17913 const bool lower_boundary_is_closer = F == 0 && E > 1;
17914 const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17915 const diyfp m_minus = lower_boundary_is_closer
17916 ? diyfp((4 * v.f) - 1, v.e - 2) // (B)
17917 : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17918
17919 // Determine the normalized w+ = m+.
17920 const diyfp w_plus = diyfp::normalize(m_plus);
17921
17922 // Determine w- = m- such that e_(w-) = e_(w+).
17923 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17924
17925 return {diyfp::normalize(v), w_minus, w_plus};
17926}
17927
17928// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17929// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17930// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17931//
17932// alpha <= e = e_c + e_w + q <= gamma
17933//
17934// or
17935//
17936// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17937// <= f_c * f_w * 2^gamma
17938//
17939// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17940//
17941// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17942//
17943// or
17944//
17945// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17946//
17947// The choice of (alpha,gamma) determines the size of the table and the form of
17948// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17949// in practice:
17950//
17951// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17952// processed independently: An integral part p1, and a fractional part p2:
17953//
17954// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17955// = (f div 2^-e) + (f mod 2^-e) * 2^e
17956// = p1 + p2 * 2^e
17957//
17958// The conversion of p1 into decimal form requires a series of divisions and
17959// modulos by (a power of) 10. These operations are faster for 32-bit than for
17960// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17961// achieved by choosing
17962//
17963// -e >= 32 or e <= -32 := gamma
17964//
17965// In order to convert the fractional part
17966//
17967// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17968//
17969// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17970// d[-i] are extracted in order:
17971//
17972// (10 * p2) div 2^-e = d[-1]
17973// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17974//
17975// The multiplication by 10 must not overflow. It is sufficient to choose
17976//
17977// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17978//
17979// Since p2 = f mod 2^-e < 2^-e,
17980//
17981// -e <= 60 or e >= -60 := alpha
17982
17983constexpr int kAlpha = -60;
17984constexpr int kGamma = -32;
17985
17986struct cached_power // c = f * 2^e ~= 10^k
17987{
17988 std::uint64_t f;
17989 int e;
17990 int k;
17991};
17992
18001{
18002 // Now
18003 //
18004 // alpha <= e_c + e + q <= gamma (1)
18005 // ==> f_c * 2^alpha <= c * 2^e * 2^q
18006 //
18007 // and since the c's are normalized, 2^(q-1) <= f_c,
18008 //
18009 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
18010 // ==> 2^(alpha - e - 1) <= c
18011 //
18012 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
18013 //
18014 // k = ceil( log_10( 2^(alpha - e - 1) ) )
18015 // = ceil( (alpha - e - 1) * log_10(2) )
18016 //
18017 // From the paper:
18018 // "In theory the result of the procedure could be wrong since c is rounded,
18019 // and the computation itself is approximated [...]. In practice, however,
18020 // this simple function is sufficient."
18021 //
18022 // For IEEE double precision floating-point numbers converted into
18023 // normalized diyfp's w = f * 2^e, with q = 64,
18024 //
18025 // e >= -1022 (min IEEE exponent)
18026 // -52 (p - 1)
18027 // -52 (p - 1, possibly normalize denormal IEEE numbers)
18028 // -11 (normalize the diyfp)
18029 // = -1137
18030 //
18031 // and
18032 //
18033 // e <= +1023 (max IEEE exponent)
18034 // -52 (p - 1)
18035 // -11 (normalize the diyfp)
18036 // = 960
18037 //
18038 // This binary exponent range [-1137,960] results in a decimal exponent
18039 // range [-307,324]. One does not need to store a cached power for each
18040 // k in this range. For each such k it suffices to find a cached power
18041 // such that the exponent of the product lies in [alpha,gamma].
18042 // This implies that the difference of the decimal exponents of adjacent
18043 // table entries must be less than or equal to
18044 //
18045 // floor( (gamma - alpha) * log_10(2) ) = 8.
18046 //
18047 // (A smaller distance gamma-alpha would require a larger table.)
18048
18049 // NB:
18050 // Actually, this function returns c, such that -60 <= e_c + e + 64 <= -34.
18051
18052 constexpr int kCachedPowersMinDecExp = -300;
18053 constexpr int kCachedPowersDecStep = 8;
18054
18055 static constexpr std::array<cached_power, 79> kCachedPowers =
18056 {
18057 {
18058 { 0xAB70FE17C79AC6CA, -1060, -300 },
18059 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18060 { 0xBE5691EF416BD60C, -1007, -284 },
18061 { 0x8DD01FAD907FFC3C, -980, -276 },
18062 { 0xD3515C2831559A83, -954, -268 },
18063 { 0x9D71AC8FADA6C9B5, -927, -260 },
18064 { 0xEA9C227723EE8BCB, -901, -252 },
18065 { 0xAECC49914078536D, -874, -244 },
18066 { 0x823C12795DB6CE57, -847, -236 },
18067 { 0xC21094364DFB5637, -821, -228 },
18068 { 0x9096EA6F3848984F, -794, -220 },
18069 { 0xD77485CB25823AC7, -768, -212 },
18070 { 0xA086CFCD97BF97F4, -741, -204 },
18071 { 0xEF340A98172AACE5, -715, -196 },
18072 { 0xB23867FB2A35B28E, -688, -188 },
18073 { 0x84C8D4DFD2C63F3B, -661, -180 },
18074 { 0xC5DD44271AD3CDBA, -635, -172 },
18075 { 0x936B9FCEBB25C996, -608, -164 },
18076 { 0xDBAC6C247D62A584, -582, -156 },
18077 { 0xA3AB66580D5FDAF6, -555, -148 },
18078 { 0xF3E2F893DEC3F126, -529, -140 },
18079 { 0xB5B5ADA8AAFF80B8, -502, -132 },
18080 { 0x87625F056C7C4A8B, -475, -124 },
18081 { 0xC9BCFF6034C13053, -449, -116 },
18082 { 0x964E858C91BA2655, -422, -108 },
18083 { 0xDFF9772470297EBD, -396, -100 },
18084 { 0xA6DFBD9FB8E5B88F, -369, -92 },
18085 { 0xF8A95FCF88747D94, -343, -84 },
18086 { 0xB94470938FA89BCF, -316, -76 },
18087 { 0x8A08F0F8BF0F156B, -289, -68 },
18088 { 0xCDB02555653131B6, -263, -60 },
18089 { 0x993FE2C6D07B7FAC, -236, -52 },
18090 { 0xE45C10C42A2B3B06, -210, -44 },
18091 { 0xAA242499697392D3, -183, -36 },
18092 { 0xFD87B5F28300CA0E, -157, -28 },
18093 { 0xBCE5086492111AEB, -130, -20 },
18094 { 0x8CBCCC096F5088CC, -103, -12 },
18095 { 0xD1B71758E219652C, -77, -4 },
18096 { 0x9C40000000000000, -50, 4 },
18097 { 0xE8D4A51000000000, -24, 12 },
18098 { 0xAD78EBC5AC620000, 3, 20 },
18099 { 0x813F3978F8940984, 30, 28 },
18100 { 0xC097CE7BC90715B3, 56, 36 },
18101 { 0x8F7E32CE7BEA5C70, 83, 44 },
18102 { 0xD5D238A4ABE98068, 109, 52 },
18103 { 0x9F4F2726179A2245, 136, 60 },
18104 { 0xED63A231D4C4FB27, 162, 68 },
18105 { 0xB0DE65388CC8ADA8, 189, 76 },
18106 { 0x83C7088E1AAB65DB, 216, 84 },
18107 { 0xC45D1DF942711D9A, 242, 92 },
18108 { 0x924D692CA61BE758, 269, 100 },
18109 { 0xDA01EE641A708DEA, 295, 108 },
18110 { 0xA26DA3999AEF774A, 322, 116 },
18111 { 0xF209787BB47D6B85, 348, 124 },
18112 { 0xB454E4A179DD1877, 375, 132 },
18113 { 0x865B86925B9BC5C2, 402, 140 },
18114 { 0xC83553C5C8965D3D, 428, 148 },
18115 { 0x952AB45CFA97A0B3, 455, 156 },
18116 { 0xDE469FBD99A05FE3, 481, 164 },
18117 { 0xA59BC234DB398C25, 508, 172 },
18118 { 0xF6C69A72A3989F5C, 534, 180 },
18119 { 0xB7DCBF5354E9BECE, 561, 188 },
18120 { 0x88FCF317F22241E2, 588, 196 },
18121 { 0xCC20CE9BD35C78A5, 614, 204 },
18122 { 0x98165AF37B2153DF, 641, 212 },
18123 { 0xE2A0B5DC971F303A, 667, 220 },
18124 { 0xA8D9D1535CE3B396, 694, 228 },
18125 { 0xFB9B7CD9A4A7443C, 720, 236 },
18126 { 0xBB764C4CA7A44410, 747, 244 },
18127 { 0x8BAB8EEFB6409C1A, 774, 252 },
18128 { 0xD01FEF10A657842C, 800, 260 },
18129 { 0x9B10A4E5E9913129, 827, 268 },
18130 { 0xE7109BFBA19C0C9D, 853, 276 },
18131 { 0xAC2820D9623BF429, 880, 284 },
18132 { 0x80444B5E7AA7CF85, 907, 292 },
18133 { 0xBF21E44003ACDD2D, 933, 300 },
18134 { 0x8E679C2F5E44FF8F, 960, 308 },
18135 { 0xD433179D9C8CB841, 986, 316 },
18136 { 0x9E19DB92B4E31BA9, 1013, 324 },
18137 }
18138 };
18139
18140 // This computation gives exactly the same results for k as
18141 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18142 // for |e| <= 1500, but doesn't require floating-point operations.
18143 // NB: log_10(2) ~= 78913 / 2^18
18144 JSON_ASSERT(e >= -1500);
18145 JSON_ASSERT(e <= 1500);
18146 const int f = kAlpha - e - 1;
18147 const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18148
18149 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18150 JSON_ASSERT(index >= 0);
18151 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18152
18153 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18154 JSON_ASSERT(kAlpha <= cached.e + e + 64);
18155 JSON_ASSERT(kGamma >= cached.e + e + 64);
18156
18157 return cached;
18158}
18159
18164inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18165{
18166 // LCOV_EXCL_START
18167 if (n >= 1000000000)
18168 {
18169 pow10 = 1000000000;
18170 return 10;
18171 }
18172 // LCOV_EXCL_STOP
18173 if (n >= 100000000)
18174 {
18175 pow10 = 100000000;
18176 return 9;
18177 }
18178 if (n >= 10000000)
18179 {
18180 pow10 = 10000000;
18181 return 8;
18182 }
18183 if (n >= 1000000)
18184 {
18185 pow10 = 1000000;
18186 return 7;
18187 }
18188 if (n >= 100000)
18189 {
18190 pow10 = 100000;
18191 return 6;
18192 }
18193 if (n >= 10000)
18194 {
18195 pow10 = 10000;
18196 return 5;
18197 }
18198 if (n >= 1000)
18199 {
18200 pow10 = 1000;
18201 return 4;
18202 }
18203 if (n >= 100)
18204 {
18205 pow10 = 100;
18206 return 3;
18207 }
18208 if (n >= 10)
18209 {
18210 pow10 = 10;
18211 return 2;
18212 }
18213
18214 pow10 = 1;
18215 return 1;
18216}
18217
18218inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18219 std::uint64_t rest, std::uint64_t ten_k)
18220{
18221 JSON_ASSERT(len >= 1);
18222 JSON_ASSERT(dist <= delta);
18223 JSON_ASSERT(rest <= delta);
18224 JSON_ASSERT(ten_k > 0);
18225
18226 // <--------------------------- delta ---->
18227 // <---- dist --------->
18228 // --------------[------------------+-------------------]--------------
18229 // M- w M+
18230 //
18231 // ten_k
18232 // <------>
18233 // <---- rest ---->
18234 // --------------[------------------+----+--------------]--------------
18235 // w V
18236 // = buf * 10^k
18237 //
18238 // ten_k represents a unit-in-the-last-place in the decimal representation
18239 // stored in buf.
18240 // Decrement buf by ten_k while this takes buf closer to w.
18241
18242 // The tests are written in this order to avoid overflow in unsigned
18243 // integer arithmetic.
18244
18245 while (rest < dist
18246 && delta - rest >= ten_k
18247 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18248 {
18249 JSON_ASSERT(buf[len - 1] != '0');
18250 buf[len - 1]--;
18251 rest += ten_k;
18252 }
18253}
18254
18259inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18260 diyfp M_minus, diyfp w, diyfp M_plus)
18261{
18262 static_assert(kAlpha >= -60, "internal error");
18263 static_assert(kGamma <= -32, "internal error");
18264
18265 // Generates the digits (and the exponent) of a decimal floating-point
18266 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18267 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18268 //
18269 // <--------------------------- delta ---->
18270 // <---- dist --------->
18271 // --------------[------------------+-------------------]--------------
18272 // M- w M+
18273 //
18274 // Grisu2 generates the digits of M+ from left to right and stops as soon as
18275 // V is in [M-,M+].
18276
18277 JSON_ASSERT(M_plus.e >= kAlpha);
18278 JSON_ASSERT(M_plus.e <= kGamma);
18279
18280 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18281 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
18282
18283 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18284 //
18285 // M+ = f * 2^e
18286 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18287 // = ((p1 ) * 2^-e + (p2 )) * 2^e
18288 // = p1 + p2 * 2^e
18289
18290 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18291
18292 auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
18293 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
18294
18295 // 1)
18296 //
18297 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18298
18299 JSON_ASSERT(p1 > 0);
18300
18301 std::uint32_t pow10{};
18302 const int k = find_largest_pow10(p1, pow10);
18303
18304 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18305 //
18306 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18307 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
18308 //
18309 // M+ = p1 + p2 * 2^e
18310 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
18311 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18312 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
18313 //
18314 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18315 //
18316 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18317 //
18318 // but stop as soon as
18319 //
18320 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18321
18322 int n = k;
18323 while (n > 0)
18324 {
18325 // Invariants:
18326 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
18327 // pow10 = 10^(n-1) <= p1 < 10^n
18328 //
18329 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
18330 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
18331 //
18332 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18333 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18334 //
18335 JSON_ASSERT(d <= 9);
18336 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18337 //
18338 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18339 //
18340 p1 = r;
18341 n--;
18342 //
18343 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
18344 // pow10 = 10^n
18345 //
18346
18347 // Now check if enough digits have been generated.
18348 // Compute
18349 //
18350 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18351 //
18352 // Note:
18353 // Since rest and delta share the same exponent e, it suffices to
18354 // compare the significands.
18355 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18356 if (rest <= delta)
18357 {
18358 // V = buffer * 10^n, with M- <= V <= M+.
18359
18360 decimal_exponent += n;
18361
18362 // We may now just stop. But instead, it looks as if the buffer
18363 // could be decremented to bring V closer to w.
18364 //
18365 // pow10 = 10^n is now 1 ulp in the decimal representation V.
18366 // The rounding procedure works with diyfp's with an implicit
18367 // exponent of e.
18368 //
18369 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18370 //
18371 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18372 grisu2_round(buffer, length, dist, delta, rest, ten_n);
18373
18374 return;
18375 }
18376
18377 pow10 /= 10;
18378 //
18379 // pow10 = 10^(n-1) <= p1 < 10^n
18380 // Invariants restored.
18381 }
18382
18383 // 2)
18384 //
18385 // The digits of the integral part have been generated:
18386 //
18387 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18388 // = buffer + p2 * 2^e
18389 //
18390 // Now generate the digits of the fractional part p2 * 2^e.
18391 //
18392 // Note:
18393 // No decimal point is generated: the exponent is adjusted instead.
18394 //
18395 // p2 actually represents the fraction
18396 //
18397 // p2 * 2^e
18398 // = p2 / 2^-e
18399 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
18400 //
18401 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18402 //
18403 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18404 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18405 //
18406 // using
18407 //
18408 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18409 // = ( d) * 2^-e + ( r)
18410 //
18411 // or
18412 // 10^m * p2 * 2^e = d + r * 2^e
18413 //
18414 // i.e.
18415 //
18416 // M+ = buffer + p2 * 2^e
18417 // = buffer + 10^-m * (d + r * 2^e)
18418 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18419 //
18420 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18421
18422 JSON_ASSERT(p2 > delta);
18423
18424 int m = 0;
18425 for (;;)
18426 {
18427 // Invariant:
18428 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18429 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
18430 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
18431 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18432 //
18433 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18434 p2 *= 10;
18435 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
18436 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18437 //
18438 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18439 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18440 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18441 //
18442 JSON_ASSERT(d <= 9);
18443 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18444 //
18445 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18446 //
18447 p2 = r;
18448 m++;
18449 //
18450 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18451 // Invariant restored.
18452
18453 // Check if enough digits have been generated.
18454 //
18455 // 10^-m * p2 * 2^e <= delta * 2^e
18456 // p2 * 2^e <= 10^m * delta * 2^e
18457 // p2 <= 10^m * delta
18458 delta *= 10;
18459 dist *= 10;
18460 if (p2 <= delta)
18461 {
18462 break;
18463 }
18464 }
18465
18466 // V = buffer * 10^-m, with M- <= V <= M+.
18467
18468 decimal_exponent -= m;
18469
18470 // 1 ulp in the decimal representation is now 10^-m.
18471 // Since delta and dist are now scaled by 10^m, we need to do the
18472 // same with ulp in order to keep the units in sync.
18473 //
18474 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18475 //
18476 const std::uint64_t ten_m = one.f;
18477 grisu2_round(buffer, length, dist, delta, p2, ten_m);
18478
18479 // By construction this algorithm generates the shortest possible decimal
18480 // number (Loitsch, Theorem 6.2) which rounds back to w.
18481 // For an input number of precision p, at least
18482 //
18483 // N = 1 + ceil(p * log_10(2))
18484 //
18485 // decimal digits are sufficient to identify all binary floating-point
18486 // numbers (Matula, "In-and-Out conversions").
18487 // This implies that the algorithm does not produce more than N decimal
18488 // digits.
18489 //
18490 // N = 17 for p = 53 (IEEE double precision)
18491 // N = 9 for p = 24 (IEEE single precision)
18492}
18493
18500inline void grisu2(char* buf, int& len, int& decimal_exponent,
18501 diyfp m_minus, diyfp v, diyfp m_plus)
18502{
18503 JSON_ASSERT(m_plus.e == m_minus.e);
18504 JSON_ASSERT(m_plus.e == v.e);
18505
18506 // --------(-----------------------+-----------------------)-------- (A)
18507 // m- v m+
18508 //
18509 // --------------------(-----------+-----------------------)-------- (B)
18510 // m- v m+
18511 //
18512 // First scale v (and m- and m+) such that the exponent is in the range
18513 // [alpha, gamma].
18514
18515 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18516
18517 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18518
18519 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18520 const diyfp w = diyfp::mul(v, c_minus_k);
18521 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18522 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
18523
18524 // ----(---+---)---------------(---+---)---------------(---+---)----
18525 // w- w w+
18526 // = c*m- = c*v = c*m+
18527 //
18528 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18529 // w+ are now off by a small amount.
18530 // In fact:
18531 //
18532 // w - v * 10^k < 1 ulp
18533 //
18534 // To account for this inaccuracy, add resp. subtract 1 ulp.
18535 //
18536 // --------+---[---------------(---+---)---------------]---+--------
18537 // w- M- w M+ w+
18538 //
18539 // Now any number in [M-, M+] (bounds included) will round to w when input,
18540 // regardless of how the input rounding algorithm breaks ties.
18541 //
18542 // And digit_gen generates the shortest possible such number in [M-, M+].
18543 // Note that this does not mean that Grisu2 always generates the shortest
18544 // possible number in the interval (m-, m+).
18545 const diyfp M_minus(w_minus.f + 1, w_minus.e);
18546 const diyfp M_plus (w_plus.f - 1, w_plus.e );
18547
18548 decimal_exponent = -cached.k; // = -(-k) = k
18549
18550 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18551}
18552
18558template<typename FloatType>
18560void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18561{
18562 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18563 "internal error: not enough precision");
18564
18565 JSON_ASSERT(std::isfinite(value));
18566 JSON_ASSERT(value > 0);
18567
18568 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18569 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18570 // decimal representations are not exactly "short".
18571 //
18572 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18573 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18574 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18575 // does.
18576 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18577 // representation using the corresponding std::from_chars function recovers value exactly". That
18578 // indicates that single precision floating-point numbers should be recovered using
18579 // 'std::strtof'.
18580 //
18581 // NB: If the neighbors are computed for single-precision numbers, there is a single float
18582 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18583 // value is off by 1 ulp.
18584#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18585 const boundaries w = compute_boundaries(static_cast<double>(value));
18586#else
18588#endif
18589
18590 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18591}
18592
18600inline char* append_exponent(char* buf, int e)
18601{
18602 JSON_ASSERT(e > -1000);
18603 JSON_ASSERT(e < 1000);
18604
18605 if (e < 0)
18606 {
18607 e = -e;
18608 *buf++ = '-';
18609 }
18610 else
18611 {
18612 *buf++ = '+';
18613 }
18614
18615 auto k = static_cast<std::uint32_t>(e);
18616 if (k < 10)
18617 {
18618 // Always print at least two digits in the exponent.
18619 // This is for compatibility with printf("%g").
18620 *buf++ = '0';
18621 *buf++ = static_cast<char>('0' + k);
18622 }
18623 else if (k < 100)
18624 {
18625 *buf++ = static_cast<char>('0' + (k / 10));
18626 k %= 10;
18627 *buf++ = static_cast<char>('0' + k);
18628 }
18629 else
18630 {
18631 *buf++ = static_cast<char>('0' + (k / 100));
18632 k %= 100;
18633 *buf++ = static_cast<char>('0' + (k / 10));
18634 k %= 10;
18635 *buf++ = static_cast<char>('0' + k);
18636 }
18637
18638 return buf;
18639}
18640
18652inline char* format_buffer(char* buf, int len, int decimal_exponent,
18653 int min_exp, int max_exp)
18654{
18655 JSON_ASSERT(min_exp < 0);
18656 JSON_ASSERT(max_exp > 0);
18657
18658 const int k = len;
18659 const int n = len + decimal_exponent;
18660
18661 // v = buf * 10^(n-k)
18662 // k is the length of the buffer (number of decimal digits)
18663 // n is the position of the decimal point relative to the start of the buffer.
18664
18665 if (k <= n && n <= max_exp)
18666 {
18667 // digits[000]
18668 // len <= max_exp + 2
18669
18670 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18671 // Make it look like a floating-point number (#362, #378)
18672 buf[n + 0] = '.';
18673 buf[n + 1] = '0';
18674 return buf + (static_cast<size_t>(n) + 2);
18675 }
18676
18677 if (0 < n && n <= max_exp)
18678 {
18679 // dig.its
18680 // len <= max_digits10 + 1
18681
18682 JSON_ASSERT(k > n);
18683
18684 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18685 buf[n] = '.';
18686 return buf + (static_cast<size_t>(k) + 1U);
18687 }
18688
18689 if (min_exp < n && n <= 0)
18690 {
18691 // 0.[000]digits
18692 // len <= 2 + (-min_exp - 1) + max_digits10
18693
18694 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18695 buf[0] = '0';
18696 buf[1] = '.';
18697 std::memset(buf + 2, '0', static_cast<size_t>(-n));
18698 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18699 }
18700
18701 if (k == 1)
18702 {
18703 // dE+123
18704 // len <= 1 + 5
18705
18706 buf += 1;
18707 }
18708 else
18709 {
18710 // d.igitsE+123
18711 // len <= max_digits10 + 1 + 5
18712
18713 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18714 buf[1] = '.';
18715 buf += 1 + static_cast<size_t>(k);
18716 }
18717
18718 *buf++ = 'e';
18719 return append_exponent(buf, n - 1);
18720}
18721
18722} // namespace dtoa_impl
18723
18734template<typename FloatType>
18737char* to_chars(char* first, const char* last, FloatType value)
18738{
18739 static_cast<void>(last); // maybe unused - fix warning
18740 JSON_ASSERT(std::isfinite(value));
18741
18742 // Use signbit(value) instead of (value < 0) since signbit works for -0.
18743 if (std::signbit(value))
18744 {
18745 value = -value;
18746 *first++ = '-';
18747 }
18748
18749#ifdef __GNUC__
18750#pragma GCC diagnostic push
18751#pragma GCC diagnostic ignored "-Wfloat-equal"
18752#endif
18753 if (value == 0) // +-0
18754 {
18755 *first++ = '0';
18756 // Make it look like a floating-point number (#362, #378)
18757 *first++ = '.';
18758 *first++ = '0';
18759 return first;
18760 }
18761#ifdef __GNUC__
18762#pragma GCC diagnostic pop
18763#endif
18764
18765 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18766
18767 // Compute v = buffer * 10^decimal_exponent.
18768 // The decimal digits are stored in the buffer, which needs to be interpreted
18769 // as an unsigned decimal integer.
18770 // len is the length of the buffer, i.e., the number of decimal digits.
18771 int len = 0;
18772 int decimal_exponent = 0;
18773 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18774
18775 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18776
18777 // Format the buffer like printf("%.*g", prec, value)
18778 constexpr int kMinExp = -4;
18779 // Use digits10 here to increase compatibility with version 2.
18780 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18781
18782 JSON_ASSERT(last - first >= kMaxExp + 2);
18783 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18784 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18785
18786 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18787}
18788
18789} // namespace detail
18791
18792// #include <nlohmann/detail/exceptions.hpp>
18793
18794// #include <nlohmann/detail/macro_scope.hpp>
18795
18796// #include <nlohmann/detail/meta/cpp_future.hpp>
18797
18798// #include <nlohmann/detail/output/binary_writer.hpp>
18799
18800// #include <nlohmann/detail/output/output_adapters.hpp>
18801
18802// #include <nlohmann/detail/string_concat.hpp>
18803
18804// #include <nlohmann/detail/value_t.hpp>
18805
18806
18808namespace detail
18809{
18810
18812// serialization //
18814
18817{
18821};
18822
18823template<typename BasicJsonType>
18825{
18826 using string_t = typename BasicJsonType::string_t;
18827 using number_float_t = typename BasicJsonType::number_float_t;
18828 using number_integer_t = typename BasicJsonType::number_integer_t;
18829 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18830 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18831 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18832 static constexpr std::uint8_t UTF8_REJECT = 1;
18833
18834 public:
18842 : o(std::move(s))
18843 , loc(std::localeconv())
18844 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18845 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18846 , indent_char(ichar)
18848 , error_handler(error_handler_)
18849 {}
18850
18851 // deleted because of pointer members
18852 serializer(const serializer&) = delete;
18856 ~serializer() = default;
18857
18880 void dump(const BasicJsonType& val,
18881 const bool pretty_print,
18882 const bool ensure_ascii,
18883 const unsigned int indent_step,
18884 const unsigned int current_indent = 0)
18885 {
18886 switch (val.m_data.m_type)
18887 {
18888 case value_t::object:
18889 {
18890 if (val.m_data.m_value.object->empty())
18891 {
18892 o->write_characters("{}", 2);
18893 return;
18894 }
18895
18896 if (pretty_print)
18897 {
18898 o->write_characters("{\n", 2);
18899
18900 // variable to hold indentation for recursive calls
18901 const auto new_indent = current_indent + indent_step;
18902 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18903 {
18904 indent_string.resize(indent_string.size() * 2, ' ');
18905 }
18906
18907 // first n-1 elements
18908 auto i = val.m_data.m_value.object->cbegin();
18909 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18910 {
18911 o->write_characters(indent_string.c_str(), new_indent);
18912 o->write_character('\"');
18913 dump_escaped(i->first, ensure_ascii);
18914 o->write_characters("\": ", 3);
18915 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18916 o->write_characters(",\n", 2);
18917 }
18918
18919 // last element
18920 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18921 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18922 o->write_characters(indent_string.c_str(), new_indent);
18923 o->write_character('\"');
18924 dump_escaped(i->first, ensure_ascii);
18925 o->write_characters("\": ", 3);
18926 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18927
18928 o->write_character('\n');
18929 o->write_characters(indent_string.c_str(), current_indent);
18930 o->write_character('}');
18931 }
18932 else
18933 {
18934 o->write_character('{');
18935
18936 // first n-1 elements
18937 auto i = val.m_data.m_value.object->cbegin();
18938 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18939 {
18940 o->write_character('\"');
18941 dump_escaped(i->first, ensure_ascii);
18942 o->write_characters("\":", 2);
18943 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18944 o->write_character(',');
18945 }
18946
18947 // last element
18948 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18949 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18950 o->write_character('\"');
18951 dump_escaped(i->first, ensure_ascii);
18952 o->write_characters("\":", 2);
18953 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18954
18955 o->write_character('}');
18956 }
18957
18958 return;
18959 }
18960
18961 case value_t::array:
18962 {
18963 if (val.m_data.m_value.array->empty())
18964 {
18965 o->write_characters("[]", 2);
18966 return;
18967 }
18968
18969 if (pretty_print)
18970 {
18971 o->write_characters("[\n", 2);
18972
18973 // variable to hold indentation for recursive calls
18974 const auto new_indent = current_indent + indent_step;
18975 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18976 {
18977 indent_string.resize(indent_string.size() * 2, ' ');
18978 }
18979
18980 // first n-1 elements
18981 for (auto i = val.m_data.m_value.array->cbegin();
18982 i != val.m_data.m_value.array->cend() - 1; ++i)
18983 {
18984 o->write_characters(indent_string.c_str(), new_indent);
18985 dump(*i, true, ensure_ascii, indent_step, new_indent);
18986 o->write_characters(",\n", 2);
18987 }
18988
18989 // last element
18990 JSON_ASSERT(!val.m_data.m_value.array->empty());
18991 o->write_characters(indent_string.c_str(), new_indent);
18992 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18993
18994 o->write_character('\n');
18995 o->write_characters(indent_string.c_str(), current_indent);
18996 o->write_character(']');
18997 }
18998 else
18999 {
19000 o->write_character('[');
19001
19002 // first n-1 elements
19003 for (auto i = val.m_data.m_value.array->cbegin();
19004 i != val.m_data.m_value.array->cend() - 1; ++i)
19005 {
19006 dump(*i, false, ensure_ascii, indent_step, current_indent);
19007 o->write_character(',');
19008 }
19009
19010 // last element
19011 JSON_ASSERT(!val.m_data.m_value.array->empty());
19012 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
19013
19014 o->write_character(']');
19015 }
19016
19017 return;
19018 }
19019
19020 case value_t::string:
19021 {
19022 o->write_character('\"');
19023 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
19024 o->write_character('\"');
19025 return;
19026 }
19027
19028 case value_t::binary:
19029 {
19030 if (pretty_print)
19031 {
19032 o->write_characters("{\n", 2);
19033
19034 // variable to hold indentation for recursive calls
19035 const auto new_indent = current_indent + indent_step;
19036 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
19037 {
19038 indent_string.resize(indent_string.size() * 2, ' ');
19039 }
19040
19041 o->write_characters(indent_string.c_str(), new_indent);
19042
19043 o->write_characters("\"bytes\": [", 10);
19044
19045 if (!val.m_data.m_value.binary->empty())
19046 {
19047 for (auto i = val.m_data.m_value.binary->cbegin();
19048 i != val.m_data.m_value.binary->cend() - 1; ++i)
19049 {
19050 dump_integer(*i);
19051 o->write_characters(", ", 2);
19052 }
19053 dump_integer(val.m_data.m_value.binary->back());
19054 }
19055
19056 o->write_characters("],\n", 3);
19057 o->write_characters(indent_string.c_str(), new_indent);
19058
19059 o->write_characters("\"subtype\": ", 11);
19060 if (val.m_data.m_value.binary->has_subtype())
19061 {
19062 dump_integer(val.m_data.m_value.binary->subtype());
19063 }
19064 else
19065 {
19066 o->write_characters("null", 4);
19067 }
19068 o->write_character('\n');
19069 o->write_characters(indent_string.c_str(), current_indent);
19070 o->write_character('}');
19071 }
19072 else
19073 {
19074 o->write_characters("{\"bytes\":[", 10);
19075
19076 if (!val.m_data.m_value.binary->empty())
19077 {
19078 for (auto i = val.m_data.m_value.binary->cbegin();
19079 i != val.m_data.m_value.binary->cend() - 1; ++i)
19080 {
19081 dump_integer(*i);
19082 o->write_character(',');
19083 }
19084 dump_integer(val.m_data.m_value.binary->back());
19085 }
19086
19087 o->write_characters("],\"subtype\":", 12);
19088 if (val.m_data.m_value.binary->has_subtype())
19089 {
19090 dump_integer(val.m_data.m_value.binary->subtype());
19091 o->write_character('}');
19092 }
19093 else
19094 {
19095 o->write_characters("null}", 5);
19096 }
19097 }
19098 return;
19099 }
19100
19101 case value_t::boolean:
19102 {
19103 if (val.m_data.m_value.boolean)
19104 {
19105 o->write_characters("true", 4);
19106 }
19107 else
19108 {
19109 o->write_characters("false", 5);
19110 }
19111 return;
19112 }
19113
19115 {
19116 dump_integer(val.m_data.m_value.number_integer);
19117 return;
19118 }
19119
19121 {
19122 dump_integer(val.m_data.m_value.number_unsigned);
19123 return;
19124 }
19125
19127 {
19128 dump_float(val.m_data.m_value.number_float);
19129 return;
19130 }
19131
19132 case value_t::discarded:
19133 {
19134 o->write_characters("<discarded>", 11);
19135 return;
19136 }
19137
19138 case value_t::null:
19139 {
19140 o->write_characters("null", 4);
19141 return;
19142 }
19143
19144 default: // LCOV_EXCL_LINE
19145 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19146 }
19147 }
19148
19164 void dump_escaped(const string_t& s, const bool ensure_ascii)
19165 {
19166 std::uint32_t codepoint{};
19167 std::uint8_t state = UTF8_ACCEPT;
19168 std::size_t bytes = 0; // number of bytes written to string_buffer
19169
19170 // number of bytes written at the point of the last valid byte
19172 std::size_t undumped_chars = 0;
19173
19174 for (std::size_t i = 0; i < s.size(); ++i)
19175 {
19176 const auto byte = static_cast<std::uint8_t>(s[i]);
19177
19178 switch (decode(state, codepoint, byte))
19179 {
19180 case UTF8_ACCEPT: // decode found a new code point
19181 {
19182 switch (codepoint)
19183 {
19184 case 0x08: // backspace
19185 {
19186 string_buffer[bytes++] = '\\';
19187 string_buffer[bytes++] = 'b';
19188 break;
19189 }
19190
19191 case 0x09: // horizontal tab
19192 {
19193 string_buffer[bytes++] = '\\';
19194 string_buffer[bytes++] = 't';
19195 break;
19196 }
19197
19198 case 0x0A: // newline
19199 {
19200 string_buffer[bytes++] = '\\';
19201 string_buffer[bytes++] = 'n';
19202 break;
19203 }
19204
19205 case 0x0C: // formfeed
19206 {
19207 string_buffer[bytes++] = '\\';
19208 string_buffer[bytes++] = 'f';
19209 break;
19210 }
19211
19212 case 0x0D: // carriage return
19213 {
19214 string_buffer[bytes++] = '\\';
19215 string_buffer[bytes++] = 'r';
19216 break;
19217 }
19218
19219 case 0x22: // quotation mark
19220 {
19221 string_buffer[bytes++] = '\\';
19222 string_buffer[bytes++] = '\"';
19223 break;
19224 }
19225
19226 case 0x5C: // reverse solidus
19227 {
19228 string_buffer[bytes++] = '\\';
19229 string_buffer[bytes++] = '\\';
19230 break;
19231 }
19232
19233 default:
19234 {
19235 // escape control characters (0x00..0x1F) or, if
19236 // ensure_ascii parameter is used, non-ASCII characters
19237 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19238 {
19239 if (codepoint <= 0xFFFF)
19240 {
19241 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19242 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19243 static_cast<std::uint16_t>(codepoint)));
19244 bytes += 6;
19245 }
19246 else
19247 {
19248 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19249 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19250 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19251 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19252 bytes += 12;
19253 }
19254 }
19255 else
19256 {
19257 // copy byte to buffer (all previous bytes
19258 // been copied have in default case above)
19259 string_buffer[bytes++] = s[i];
19260 }
19261 break;
19262 }
19263 }
19264
19265 // write buffer and reset index; there must be 13 bytes
19266 // left, as this is the maximal number of bytes to be
19267 // written ("\uxxxx\uxxxx\0") for one code point
19268 if (string_buffer.size() - bytes < 13)
19269 {
19270 o->write_characters(string_buffer.data(), bytes);
19271 bytes = 0;
19272 }
19273
19274 // remember the byte position of this accept
19276 undumped_chars = 0;
19277 break;
19278 }
19279
19280 case UTF8_REJECT: // decode found invalid UTF-8 byte
19281 {
19282 switch (error_handler)
19283 {
19285 {
19286 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19287 }
19288
19291 {
19292 // in case we saw this character the first time, we
19293 // would like to read it again, because the byte
19294 // may be OK for itself, but just not OK for the
19295 // previous sequence
19296 if (undumped_chars > 0)
19297 {
19298 --i;
19299 }
19300
19301 // reset length buffer to the last accepted index;
19302 // thus removing/ignoring the invalid characters
19304
19306 {
19307 // add a replacement character
19308 if (ensure_ascii)
19309 {
19310 string_buffer[bytes++] = '\\';
19311 string_buffer[bytes++] = 'u';
19312 string_buffer[bytes++] = 'f';
19313 string_buffer[bytes++] = 'f';
19314 string_buffer[bytes++] = 'f';
19315 string_buffer[bytes++] = 'd';
19316 }
19317 else
19318 {
19322 }
19323
19324 // write buffer and reset index; there must be 13 bytes
19325 // left, as this is the maximal number of bytes to be
19326 // written ("\uxxxx\uxxxx\0") for one code point
19327 if (string_buffer.size() - bytes < 13)
19328 {
19329 o->write_characters(string_buffer.data(), bytes);
19330 bytes = 0;
19331 }
19332
19334 }
19335
19336 undumped_chars = 0;
19337
19338 // continue processing the string
19339 state = UTF8_ACCEPT;
19340 break;
19341 }
19342
19343 default: // LCOV_EXCL_LINE
19344 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19345 }
19346 break;
19347 }
19348
19349 default: // decode found yet incomplete multibyte code point
19350 {
19351 if (!ensure_ascii)
19352 {
19353 // code point will not be escaped - copy byte to buffer
19354 string_buffer[bytes++] = s[i];
19355 }
19357 break;
19358 }
19359 }
19360 }
19361
19362 // we finished processing the string
19363 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19364 {
19365 // write buffer
19366 if (bytes > 0)
19367 {
19368 o->write_characters(string_buffer.data(), bytes);
19369 }
19370 }
19371 else
19372 {
19373 // we finish reading, but do not accept: string was incomplete
19374 switch (error_handler)
19375 {
19377 {
19378 JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
19379 }
19380
19382 {
19383 // write all accepted bytes
19384 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19385 break;
19386 }
19387
19389 {
19390 // write all accepted bytes
19391 o->write_characters(string_buffer.data(), bytes_after_last_accept);
19392 // add a replacement character
19393 if (ensure_ascii)
19394 {
19395 o->write_characters("\\ufffd", 6);
19396 }
19397 else
19398 {
19399 o->write_characters("\xEF\xBF\xBD", 3);
19400 }
19401 break;
19402 }
19403
19404 default: // LCOV_EXCL_LINE
19405 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19406 }
19407 }
19408 }
19409
19410 private:
19419 unsigned int count_digits(number_unsigned_t x) noexcept
19420 {
19421 unsigned int n_digits = 1;
19422 for (;;)
19423 {
19424 if (x < 10)
19425 {
19426 return n_digits;
19427 }
19428 if (x < 100)
19429 {
19430 return n_digits + 1;
19431 }
19432 if (x < 1000)
19433 {
19434 return n_digits + 2;
19435 }
19436 if (x < 10000)
19437 {
19438 return n_digits + 3;
19439 }
19440 x = x / 10000u;
19441 n_digits += 4;
19442 }
19443 }
19444
19450 static std::string hex_bytes(std::uint8_t byte)
19451 {
19452 std::string result = "FF";
19453 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19454 result[0] = nibble_to_hex[byte / 16];
19455 result[1] = nibble_to_hex[byte % 16];
19456 return result;
19457 }
19458
19459 // templates to avoid warnings about useless casts
19460 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19461 bool is_negative_number(NumberType x)
19462 {
19463 return x < 0;
19464 }
19465
19466 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19467 bool is_negative_number(NumberType /*unused*/)
19468 {
19469 return false;
19470 }
19471
19481 template < typename NumberType, detail::enable_if_t <
19482 std::is_integral<NumberType>::value ||
19483 std::is_same<NumberType, number_unsigned_t>::value ||
19484 std::is_same<NumberType, number_integer_t>::value ||
19485 std::is_same<NumberType, binary_char_t>::value,
19486 int > = 0 >
19487 void dump_integer(NumberType x)
19488 {
19489 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19490 {
19491 {
19492 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19493 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19494 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19495 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19496 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19497 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19498 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19499 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19500 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19501 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19502 }
19503 };
19504
19505 // special case for "0"
19506 if (x == 0)
19507 {
19508 o->write_character('0');
19509 return;
19510 }
19511
19512 // use a pointer to fill the buffer
19513 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19514
19515 number_unsigned_t abs_value;
19516
19517 unsigned int n_chars{};
19518
19519 if (is_negative_number(x))
19520 {
19521 *buffer_ptr = '-';
19522 abs_value = remove_sign(static_cast<number_integer_t>(x));
19523
19524 // account one more byte for the minus sign
19525 n_chars = 1 + count_digits(abs_value);
19526 }
19527 else
19528 {
19529 abs_value = static_cast<number_unsigned_t>(x);
19530 n_chars = count_digits(abs_value);
19531 }
19532
19533 // spare 1 byte for '\0'
19534 JSON_ASSERT(n_chars < number_buffer.size() - 1);
19535
19536 // jump to the end to generate the string from backward,
19537 // so we later avoid reversing the result
19538 buffer_ptr += static_cast<typename decltype(number_buffer)::difference_type>(n_chars);
19539
19540 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19541 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19542 while (abs_value >= 100)
19543 {
19544 const auto digits_index = static_cast<unsigned>((abs_value % 100));
19545 abs_value /= 100;
19546 *(--buffer_ptr) = digits_to_99[digits_index][1];
19547 *(--buffer_ptr) = digits_to_99[digits_index][0];
19548 }
19549
19550 if (abs_value >= 10)
19551 {
19552 const auto digits_index = static_cast<unsigned>(abs_value);
19553 *(--buffer_ptr) = digits_to_99[digits_index][1];
19554 *(--buffer_ptr) = digits_to_99[digits_index][0];
19555 }
19556 else
19557 {
19558 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19559 }
19560
19561 o->write_characters(number_buffer.data(), n_chars);
19562 }
19563
19572 void dump_float(number_float_t x)
19573 {
19574 // NaN / inf
19575 if (!std::isfinite(x))
19576 {
19577 o->write_characters("null", 4);
19578 return;
19579 }
19580
19581 // If number_float_t is an IEEE-754 single or double precision number,
19582 // use the Grisu2 algorithm to produce short numbers which are
19583 // guaranteed to round-trip, using strtof and strtod, resp.
19584 //
19585 // NB: The test below works if <long double> == <double>.
19586 static constexpr bool is_ieee_single_or_double
19587 = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
19588 (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
19589
19590 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19591 }
19592
19593 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19594 {
19595 auto* begin = number_buffer.data();
19596 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19597
19598 o->write_characters(begin, static_cast<size_t>(end - begin));
19599 }
19600
19601 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19602 {
19603 // get the number of digits for a float -> text -> float round-trip
19604 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19605
19606 // the actual conversion
19607 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19608 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19609
19610 // negative value indicates an error
19611 JSON_ASSERT(len > 0);
19612 // check if the buffer was large enough
19613 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19614
19615 // erase thousands separators
19616 if (thousands_sep != '\0')
19617 {
19618 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19619 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19620 std::fill(end, number_buffer.end(), '\0');
19621 JSON_ASSERT((end - number_buffer.begin()) <= len);
19622 len = (end - number_buffer.begin());
19623 }
19624
19625 // convert decimal point to '.'
19626 if (decimal_point != '\0' && decimal_point != '.')
19627 {
19628 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19629 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19630 if (dec_pos != number_buffer.end())
19631 {
19632 *dec_pos = '.';
19633 }
19634 }
19635
19636 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19637
19638 // determine if we need to append ".0"
19639 const bool value_is_int_like =
19640 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19641 [](char c)
19642 {
19643 return c == '.' || c == 'e';
19644 });
19645
19646 if (value_is_int_like)
19647 {
19648 o->write_characters(".0", 2);
19649 }
19650 }
19651
19673 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19674 {
19675 static const std::array<std::uint8_t, 400> utf8d =
19676 {
19677 {
19678 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
19679 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
19680 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
19681 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
19682 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
19683 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
19684 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
19685 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19686 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19687 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19688 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
19689 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
19690 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
19691 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
19692 }
19693 };
19694
19695 JSON_ASSERT(byte < utf8d.size());
19696 const std::uint8_t type = utf8d[byte];
19697
19698 codep = (state != UTF8_ACCEPT)
19699 ? (byte & 0x3fu) | (codep << 6u)
19700 : (0xFFu >> type) & (byte);
19701
19702 const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19703 JSON_ASSERT(index < utf8d.size());
19704 state = utf8d[index];
19705 return state;
19706 }
19707
19708 /*
19709 * Overload to make the compiler happy while it is instantiating
19710 * dump_integer for number_unsigned_t.
19711 * Must never be called.
19712 */
19713 number_unsigned_t remove_sign(number_unsigned_t x)
19714 {
19715 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19716 return x; // LCOV_EXCL_LINE
19717 }
19718
19719 /*
19720 * Helper function for dump_integer
19721 *
19722 * This function takes a negative signed integer and returns its absolute
19723 * value as an unsigned integer. The plus/minus shuffling is necessary as we
19724 * cannot directly remove the sign of an arbitrary signed integer as the
19725 * absolute values of INT_MIN and INT_MAX are usually not the same. See
19726 * #1708 for details.
19727 */
19728 number_unsigned_t remove_sign(number_integer_t x) noexcept
19729 {
19730 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19731 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19732 }
19733
19734 private:
19736 output_adapter_t<char> o = nullptr;
19737
19739 std::array<char, 64> number_buffer{{}};
19740
19742 const std::lconv* loc = nullptr;
19744 const char thousands_sep = '\0';
19746 const char decimal_point = '\0';
19747
19749 std::array<char, 512> string_buffer{{}};
19750
19752 const char indent_char;
19755
19758};
19759
19760} // namespace detail
19762
19763// #include <nlohmann/detail/value_t.hpp>
19764
19765// #include <nlohmann/json_fwd.hpp>
19766
19767// #include <nlohmann/ordered_map.hpp>
19768// __ _____ _____ _____
19769// __| | __| | | | JSON for Modern C++
19770// | | |__ | | | | | | version 3.12.0
19771// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19772//
19773// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19774// SPDX-License-Identifier: MIT
19775
19776
19777
19778#include <functional> // equal_to, less
19779#include <initializer_list> // initializer_list
19780#include <iterator> // input_iterator_tag, iterator_traits
19781#include <memory> // allocator
19782#include <stdexcept> // for out_of_range
19783#include <type_traits> // enable_if, is_convertible
19784#include <utility> // pair
19785#include <vector> // vector
19786
19787// #include <nlohmann/detail/macro_scope.hpp>
19788
19789// #include <nlohmann/detail/meta/type_traits.hpp>
19790
19791
19793
19796template <class Key, class T, class IgnoredLess = std::less<Key>,
19797 class Allocator = std::allocator<std::pair<const Key, T>>>
19798 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19799{
19800 using key_type = Key;
19801 using mapped_type = T;
19802 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19803 using iterator = typename Container::iterator;
19804 using const_iterator = typename Container::const_iterator;
19805 using size_type = typename Container::size_type;
19806 using value_type = typename Container::value_type;
19807#ifdef JSON_HAS_CPP_14
19808 using key_compare = std::equal_to<>;
19809#else
19810 using key_compare = std::equal_to<Key>;
19811#endif
19812
19813 // Explicit constructors instead of `using Container::Container`
19814 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19815 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19816 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19817 template <class It>
19818 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19819 : Container{first, last, alloc} {}
19820 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19821 : Container{init, alloc} {}
19822
19823 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19824 {
19825 for (auto it = this->begin(); it != this->end(); ++it)
19826 {
19827 if (m_compare(it->first, key))
19828 {
19829 return {it, false};
19830 }
19831 }
19832 Container::emplace_back(key, std::forward<T>(t));
19833 return {std::prev(this->end()), true};
19834 }
19835
19836 template<class KeyType, detail::enable_if_t<
19838 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19839 {
19840 for (auto it = this->begin(); it != this->end(); ++it)
19841 {
19842 if (m_compare(it->first, key))
19843 {
19844 return {it, false};
19845 }
19846 }
19847 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19848 return {std::prev(this->end()), true};
19849 }
19850
19851 T& operator[](const key_type& key)
19852 {
19853 return emplace(key, T{}).first->second;
19854 }
19855
19856 template<class KeyType, detail::enable_if_t<
19858 T & operator[](KeyType && key)
19859 {
19860 return emplace(std::forward<KeyType>(key), T{}).first->second;
19861 }
19862
19863 const T& operator[](const key_type& key) const
19864 {
19865 return at(key);
19866 }
19867
19868 template<class KeyType, detail::enable_if_t<
19870 const T & operator[](KeyType && key) const
19871 {
19872 return at(std::forward<KeyType>(key));
19873 }
19874
19875 T& at(const key_type& key)
19876 {
19877 for (auto it = this->begin(); it != this->end(); ++it)
19878 {
19879 if (m_compare(it->first, key))
19880 {
19881 return it->second;
19882 }
19883 }
19884
19885 JSON_THROW(std::out_of_range("key not found"));
19886 }
19887
19888 template<class KeyType, detail::enable_if_t<
19890 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19891 {
19892 for (auto it = this->begin(); it != this->end(); ++it)
19893 {
19894 if (m_compare(it->first, key))
19895 {
19896 return it->second;
19897 }
19898 }
19899
19900 JSON_THROW(std::out_of_range("key not found"));
19901 }
19902
19903 const T& at(const key_type& key) const
19904 {
19905 for (auto it = this->begin(); it != this->end(); ++it)
19906 {
19907 if (m_compare(it->first, key))
19908 {
19909 return it->second;
19910 }
19911 }
19912
19913 JSON_THROW(std::out_of_range("key not found"));
19914 }
19915
19916 template<class KeyType, detail::enable_if_t<
19918 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19919 {
19920 for (auto it = this->begin(); it != this->end(); ++it)
19921 {
19922 if (m_compare(it->first, key))
19923 {
19924 return it->second;
19925 }
19926 }
19927
19928 JSON_THROW(std::out_of_range("key not found"));
19929 }
19930
19932 {
19933 for (auto it = this->begin(); it != this->end(); ++it)
19934 {
19935 if (m_compare(it->first, key))
19936 {
19937 // Since we cannot move const Keys, re-construct them in place
19938 for (auto next = it; ++next != this->end(); ++it)
19939 {
19940 it->~value_type(); // Destroy but keep allocation
19941 new (&*it) value_type{std::move(*next)};
19942 }
19943 Container::pop_back();
19944 return 1;
19945 }
19946 }
19947 return 0;
19948 }
19949
19950 template<class KeyType, detail::enable_if_t<
19952 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19953 {
19954 for (auto it = this->begin(); it != this->end(); ++it)
19955 {
19956 if (m_compare(it->first, key))
19957 {
19958 // Since we cannot move const Keys, re-construct them in place
19959 for (auto next = it; ++next != this->end(); ++it)
19960 {
19961 it->~value_type(); // Destroy but keep allocation
19962 new (&*it) value_type{std::move(*next)};
19963 }
19964 Container::pop_back();
19965 return 1;
19966 }
19967 }
19968 return 0;
19969 }
19970
19972 {
19973 return erase(pos, std::next(pos));
19974 }
19975
19977 {
19978 if (first == last)
19979 {
19980 return first;
19981 }
19982
19983 const auto elements_affected = std::distance(first, last);
19984 const auto offset = std::distance(Container::begin(), first);
19985
19986 // This is the start situation. We need to delete elements_affected
19987 // elements (3 in this example: e, f, g), and need to return an
19988 // iterator past the last deleted element (h in this example).
19989 // Note that offset is the distance from the start of the vector
19990 // to first. We will need this later.
19991
19992 // [ a, b, c, d, e, f, g, h, i, j ]
19993 // ^ ^
19994 // first last
19995
19996 // Since we cannot move const Keys, we re-construct them in place.
19997 // We start at first and re-construct (viz. copy) the elements from
19998 // the back of the vector. Example for the first iteration:
19999
20000 // ,--------.
20001 // v | destroy e and re-construct with h
20002 // [ a, b, c, d, e, f, g, h, i, j ]
20003 // ^ ^
20004 // it it + elements_affected
20005
20006 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
20007 {
20008 it->~value_type(); // destroy but keep allocation
20009 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
20010 }
20011
20012 // [ a, b, c, d, h, i, j, h, i, j ]
20013 // ^ ^
20014 // first last
20015
20016 // remove the unneeded elements at the end of the vector
20017 Container::resize(this->size() - static_cast<size_type>(elements_affected));
20018
20019 // [ a, b, c, d, h, i, j ]
20020 // ^ ^
20021 // first last
20022
20023 // first is now pointing past the last deleted element, but we cannot
20024 // use this iterator, because it may have been invalidated by the
20025 // resize call. Instead, we can return begin() + offset.
20026 return Container::begin() + offset;
20027 }
20028
20029 size_type count(const key_type& key) const
20030 {
20031 for (auto it = this->begin(); it != this->end(); ++it)
20032 {
20033 if (m_compare(it->first, key))
20034 {
20035 return 1;
20036 }
20037 }
20038 return 0;
20039 }
20040
20041 template<class KeyType, detail::enable_if_t<
20043 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
20044 {
20045 for (auto it = this->begin(); it != this->end(); ++it)
20046 {
20047 if (m_compare(it->first, key))
20048 {
20049 return 1;
20050 }
20051 }
20052 return 0;
20053 }
20054
20056 {
20057 for (auto it = this->begin(); it != this->end(); ++it)
20058 {
20059 if (m_compare(it->first, key))
20060 {
20061 return it;
20062 }
20063 }
20064 return Container::end();
20065 }
20066
20067 template<class KeyType, detail::enable_if_t<
20069 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20070 {
20071 for (auto it = this->begin(); it != this->end(); ++it)
20072 {
20073 if (m_compare(it->first, key))
20074 {
20075 return it;
20076 }
20077 }
20078 return Container::end();
20079 }
20080
20081 const_iterator find(const key_type& key) const
20082 {
20083 for (auto it = this->begin(); it != this->end(); ++it)
20084 {
20085 if (m_compare(it->first, key))
20086 {
20087 return it;
20088 }
20089 }
20090 return Container::end();
20091 }
20092
20093 std::pair<iterator, bool> insert( value_type&& value )
20094 {
20095 return emplace(value.first, std::move(value.second));
20096 }
20097
20098 std::pair<iterator, bool> insert( const value_type& value )
20099 {
20100 for (auto it = this->begin(); it != this->end(); ++it)
20101 {
20102 if (m_compare(it->first, value.first))
20103 {
20104 return {it, false};
20105 }
20106 }
20107 Container::push_back(value);
20108 return {--this->end(), true};
20109 }
20110
20111 template<typename InputIt>
20112 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20113 std::input_iterator_tag>::value>::type;
20114
20115 template<typename InputIt, typename = require_input_iter<InputIt>>
20116 void insert(InputIt first, InputIt last)
20117 {
20118 for (auto it = first; it != last; ++it)
20119 {
20120 insert(*it);
20121 }
20122 }
20123
20124private:
20125 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
20126};
20127
20129
20130
20131#if defined(JSON_HAS_CPP_17)
20132 #if JSON_HAS_STATIC_RTTI
20133 #include <any>
20134 #endif
20135 #include <string_view>
20136#endif
20137
20144
20164class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20165 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20166{
20167 private:
20168 template<detail::value_t> friend struct detail::external_constructor;
20169
20170 template<typename>
20171 friend class ::nlohmann::json_pointer;
20172 // can be restored when json_pointer backwards compatibility is removed
20173 // friend ::nlohmann::json_pointer<StringType>;
20174
20175 template<typename BasicJsonType, typename InputType>
20176 friend class ::nlohmann::detail::parser;
20177 friend ::nlohmann::detail::serializer<basic_json>;
20178 template<typename BasicJsonType>
20179 friend class ::nlohmann::detail::iter_impl;
20180 template<typename BasicJsonType, typename CharType>
20181 friend class ::nlohmann::detail::binary_writer;
20182 template<typename BasicJsonType, typename InputType, typename SAX>
20183 friend class ::nlohmann::detail::binary_reader;
20184 template<typename BasicJsonType, typename InputAdapterType>
20185 friend class ::nlohmann::detail::json_sax_dom_parser;
20186 template<typename BasicJsonType, typename InputAdapterType>
20187 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20188 friend class ::nlohmann::detail::exception;
20189
20191 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
20192 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20193
20195 // convenience aliases for types residing in namespace detail;
20196 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20197
20198 template<typename InputAdapterType>
20199 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20200 InputAdapterType adapter,
20202 const bool allow_exceptions = true,
20203 const bool ignore_comments = false
20204 )
20205 {
20206 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20207 std::move(cb), allow_exceptions, ignore_comments);
20208 }
20209
20210 private:
20211 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20212 template<typename BasicJsonType>
20213 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20214 template<typename BasicJsonType>
20215 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20216 template<typename Iterator>
20217 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20218 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20219
20220 template<typename CharType>
20221 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20222
20223 template<typename InputType>
20224 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20225 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20226
20228 using serializer = ::nlohmann::detail::serializer<basic_json>;
20229
20230 public:
20233 using json_pointer = ::nlohmann::json_pointer<StringType>;
20234 template<typename T, typename SFINAE>
20235 using json_serializer = JSONSerializer<T, SFINAE>;
20243 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20244
20248
20250 // exceptions //
20252
20256
20263
20265
20267 // container types //
20269
20274
20277
20282
20284 using difference_type = std::ptrdiff_t;
20286 using size_type = std::size_t;
20287
20289 using allocator_type = AllocatorType<basic_json>;
20290
20292 using pointer = typename std::allocator_traits<allocator_type>::pointer;
20294 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20295
20297 using iterator = iter_impl<basic_json>;
20299 using const_iterator = iter_impl<const basic_json>;
20301 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
20303 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
20304
20306
20310 {
20311 return allocator_type();
20312 }
20313
20318 {
20319 basic_json result;
20320
20321 result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20322 result["name"] = "JSON for Modern C++";
20323 result["url"] = "https://github.com/nlohmann/json";
20324 result["version"]["string"] =
20325 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20326 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20327 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20328 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20329 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20330 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20331
20332#ifdef _WIN32
20333 result["platform"] = "win32";
20334#elif defined __linux__
20335 result["platform"] = "linux";
20336#elif defined __APPLE__
20337 result["platform"] = "apple";
20338#elif defined __unix__
20339 result["platform"] = "unix";
20340#else
20341 result["platform"] = "unknown";
20342#endif
20343
20344#if defined(__ICC) || defined(__INTEL_COMPILER)
20345 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20346#elif defined(__clang__)
20347 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20348#elif defined(__GNUC__) || defined(__GNUG__)
20349 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20350 std::to_string(__GNUC__), '.',
20351 std::to_string(__GNUC_MINOR__), '.',
20352 std::to_string(__GNUC_PATCHLEVEL__))
20353 }
20354 };
20355#elif defined(__HP_cc) || defined(__HP_aCC)
20356 result["compiler"] = "hp"
20357#elif defined(__IBMCPP__)
20358 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20359#elif defined(_MSC_VER)
20360 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20361#elif defined(__PGI)
20362 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20363#elif defined(__SUNPRO_CC)
20364 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20365#else
20366 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20367#endif
20368
20369#if defined(_MSVC_LANG)
20370 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20371#elif defined(__cplusplus)
20372 result["compiler"]["c++"] = std::to_string(__cplusplus);
20373#else
20374 result["compiler"]["c++"] = "unknown";
20375#endif
20376 return result;
20377 }
20378
20380 // JSON value data types //
20382
20387
20392#if defined(JSON_HAS_CPP_14)
20393 // use of transparent comparator avoids unnecessary repeated construction of temporaries
20394 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20395 using default_object_comparator_t = std::less<>;
20396#else
20397 using default_object_comparator_t = std::less<StringType>;
20398#endif
20399
20402 using object_t = ObjectType<StringType,
20403 basic_json,
20405 AllocatorType<std::pair<const StringType,
20406 basic_json>>>;
20407
20410 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20411
20414 using string_t = StringType;
20415
20418 using boolean_t = BooleanType;
20419
20422 using number_integer_t = NumberIntegerType;
20423
20426 using number_unsigned_t = NumberUnsignedType;
20427
20430 using number_float_t = NumberFloatType;
20431
20434 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20435
20439
20441
20442 private:
20443
20445 template<typename T, typename... Args>
20447 static T* create(Args&& ... args)
20448 {
20449 AllocatorType<T> alloc;
20450 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20451
20452 auto deleter = [&](T * obj)
20453 {
20454 AllocatorTraits::deallocate(alloc, obj, 1);
20455 };
20456 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20457 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20458 JSON_ASSERT(obj != nullptr);
20459 return obj.release();
20460 }
20461
20463 // JSON value storage //
20465
20492 union json_value
20493 {
20495 object_t* object;
20497 array_t* array;
20499 string_t* string;
20501 binary_t* binary;
20503 boolean_t boolean;
20505 number_integer_t number_integer;
20507 number_unsigned_t number_unsigned;
20509 number_float_t number_float;
20510
20512 json_value() = default;
20514 json_value(boolean_t v) noexcept : boolean(v) {}
20516 json_value(number_integer_t v) noexcept : number_integer(v) {}
20518 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20520 json_value(number_float_t v) noexcept : number_float(v) {}
20522 json_value(value_t t)
20523 {
20524 switch (t)
20525 {
20526 case value_t::object:
20527 {
20528 object = create<object_t>();
20529 break;
20530 }
20531
20532 case value_t::array:
20533 {
20534 array = create<array_t>();
20535 break;
20536 }
20537
20538 case value_t::string:
20539 {
20540 string = create<string_t>("");
20541 break;
20542 }
20543
20544 case value_t::binary:
20545 {
20546 binary = create<binary_t>();
20547 break;
20548 }
20549
20550 case value_t::boolean:
20551 {
20552 boolean = static_cast<boolean_t>(false);
20553 break;
20554 }
20555
20556 case value_t::number_integer:
20557 {
20558 number_integer = static_cast<number_integer_t>(0);
20559 break;
20560 }
20561
20562 case value_t::number_unsigned:
20563 {
20564 number_unsigned = static_cast<number_unsigned_t>(0);
20565 break;
20566 }
20567
20568 case value_t::number_float:
20569 {
20570 number_float = static_cast<number_float_t>(0.0);
20571 break;
20572 }
20573
20574 case value_t::null:
20575 {
20576 object = nullptr; // silence warning, see #821
20577 break;
20578 }
20579
20580 case value_t::discarded:
20581 default:
20582 {
20583 object = nullptr; // silence warning, see #821
20584 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20585 {
20586 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20587 }
20588 break;
20589 }
20590 }
20591 }
20592
20594 json_value(const string_t& value) : string(create<string_t>(value)) {}
20595
20597 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20598
20600 json_value(const object_t& value) : object(create<object_t>(value)) {}
20601
20603 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20604
20606 json_value(const array_t& value) : array(create<array_t>(value)) {}
20607
20609 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20610
20612 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20613
20615 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20616
20618 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20619
20621 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20622
20623 void destroy(value_t t)
20624 {
20625 if (
20626 (t == value_t::object && object == nullptr) ||
20627 (t == value_t::array && array == nullptr) ||
20628 (t == value_t::string && string == nullptr) ||
20629 (t == value_t::binary && binary == nullptr)
20630 )
20631 {
20632 //not initialized (e.g., due to exception in the ctor)
20633 return;
20634 }
20635 if (t == value_t::array || t == value_t::object)
20636 {
20637 // flatten the current json_value to a heap-allocated stack
20638 std::vector<basic_json> stack;
20639
20640 // move the top-level items to stack
20641 if (t == value_t::array)
20642 {
20643 stack.reserve(array->size());
20644 std::move(array->begin(), array->end(), std::back_inserter(stack));
20645 }
20646 else
20647 {
20648 stack.reserve(object->size());
20649 for (auto&& it : *object)
20650 {
20651 stack.push_back(std::move(it.second));
20652 }
20653 }
20654
20655 while (!stack.empty())
20656 {
20657 // move the last item to a local variable to be processed
20658 basic_json current_item(std::move(stack.back()));
20659 stack.pop_back();
20660
20661 // if current_item is array/object, move
20662 // its children to the stack to be processed later
20663 if (current_item.is_array())
20664 {
20665 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20666
20667 current_item.m_data.m_value.array->clear();
20668 }
20669 else if (current_item.is_object())
20670 {
20671 for (auto&& it : *current_item.m_data.m_value.object)
20672 {
20673 stack.push_back(std::move(it.second));
20674 }
20675
20676 current_item.m_data.m_value.object->clear();
20677 }
20678
20679 // it's now safe that current_item gets destructed
20680 // since it doesn't have any children
20681 }
20682 }
20683
20684 switch (t)
20685 {
20686 case value_t::object:
20687 {
20688 AllocatorType<object_t> alloc;
20689 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20690 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20691 break;
20692 }
20693
20694 case value_t::array:
20695 {
20696 AllocatorType<array_t> alloc;
20697 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20698 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20699 break;
20700 }
20701
20702 case value_t::string:
20703 {
20704 AllocatorType<string_t> alloc;
20705 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20706 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20707 break;
20708 }
20709
20710 case value_t::binary:
20711 {
20712 AllocatorType<binary_t> alloc;
20713 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20714 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20715 break;
20716 }
20717
20718 case value_t::null:
20719 case value_t::boolean:
20720 case value_t::number_integer:
20721 case value_t::number_unsigned:
20722 case value_t::number_float:
20723 case value_t::discarded:
20724 default:
20725 {
20726 break;
20727 }
20728 }
20729 }
20730 };
20731
20732 private:
20751 void assert_invariant(bool check_parents = true) const noexcept
20752 {
20753 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20754 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20755 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20756 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20757
20758#if JSON_DIAGNOSTICS
20759 JSON_TRY
20760 {
20761 // cppcheck-suppress assertWithSideEffect
20762 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20763 {
20764 return j.m_parent == this;
20765 }));
20766 }
20767 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20768#endif
20769 static_cast<void>(check_parents);
20770 }
20771
20772 void set_parents()
20773 {
20774#if JSON_DIAGNOSTICS
20775 switch (m_data.m_type)
20776 {
20777 case value_t::array:
20778 {
20779 for (auto& element : *m_data.m_value.array)
20780 {
20781 element.m_parent = this;
20782 }
20783 break;
20784 }
20785
20786 case value_t::object:
20787 {
20788 for (auto& element : *m_data.m_value.object)
20789 {
20790 element.second.m_parent = this;
20791 }
20792 break;
20793 }
20794
20795 case value_t::null:
20796 case value_t::string:
20797 case value_t::boolean:
20798 case value_t::number_integer:
20799 case value_t::number_unsigned:
20800 case value_t::number_float:
20801 case value_t::binary:
20802 case value_t::discarded:
20803 default:
20804 break;
20805 }
20806#endif
20807 }
20808
20809 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20810 {
20811#if JSON_DIAGNOSTICS
20812 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20813 {
20814 (it + i)->m_parent = this;
20815 }
20816#else
20817 static_cast<void>(count_set_parents);
20818#endif
20819 return it;
20820 }
20821
20822 reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20823 {
20824#if JSON_DIAGNOSTICS
20825 if (old_capacity != detail::unknown_size())
20826 {
20827 // see https://github.com/nlohmann/json/issues/2838
20828 JSON_ASSERT(type() == value_t::array);
20829 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20830 {
20831 // capacity has changed: update all parents
20832 set_parents();
20833 return j;
20834 }
20835 }
20836
20837 // ordered_json uses a vector internally, so pointers could have
20838 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20839#ifdef JSON_HEDLEY_MSVC_VERSION
20840#pragma warning(push )
20841#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20842#endif
20844 {
20845 set_parents();
20846 return j;
20847 }
20848#ifdef JSON_HEDLEY_MSVC_VERSION
20849#pragma warning( pop )
20850#endif
20851
20852 j.m_parent = this;
20853#else
20854 static_cast<void>(j);
20855 static_cast<void>(old_capacity);
20856#endif
20857 return j;
20858 }
20859
20860 public:
20862 // JSON parser callback //
20864
20868
20872
20874 // constructors //
20876
20881
20885 : m_data(v)
20886 {
20887 assert_invariant();
20888 }
20889
20892 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20893 : basic_json(value_t::null)
20894 {
20895 assert_invariant();
20896 }
20897
20900 template < typename CompatibleType,
20904 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20905 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20906 std::forward<CompatibleType>(val))))
20907 {
20908 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20909 set_parents();
20910 assert_invariant();
20911 }
20912
20915 template < typename BasicJsonType,
20917 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20918 basic_json(const BasicJsonType& val)
20919#if JSON_DIAGNOSTIC_POSITIONS
20920 : start_position(val.start_pos()),
20921 end_position(val.end_pos())
20922#endif
20923 {
20924 using other_boolean_t = typename BasicJsonType::boolean_t;
20925 using other_number_float_t = typename BasicJsonType::number_float_t;
20926 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20927 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20928 using other_string_t = typename BasicJsonType::string_t;
20929 using other_object_t = typename BasicJsonType::object_t;
20930 using other_array_t = typename BasicJsonType::array_t;
20931 using other_binary_t = typename BasicJsonType::binary_t;
20932
20933 switch (val.type())
20934 {
20935 case value_t::boolean:
20936 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20937 break;
20938 case value_t::number_float:
20939 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20940 break;
20941 case value_t::number_integer:
20942 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20943 break;
20944 case value_t::number_unsigned:
20945 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20946 break;
20947 case value_t::string:
20948 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20949 break;
20950 case value_t::object:
20951 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20952 break;
20953 case value_t::array:
20954 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20955 break;
20956 case value_t::binary:
20957 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20958 break;
20959 case value_t::null:
20960 *this = nullptr;
20961 break;
20962 case value_t::discarded:
20963 m_data.m_type = value_t::discarded;
20964 break;
20965 default: // LCOV_EXCL_LINE
20966 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20967 }
20968 JSON_ASSERT(m_data.m_type == val.type());
20969
20970 set_parents();
20971 assert_invariant();
20972 }
20973
20977 bool type_deduction = true,
20978 value_t manual_type = value_t::array)
20979 {
20980 // check if each element is an array with two elements whose first
20981 // element is a string
20982 bool is_an_object = std::all_of(init.begin(), init.end(),
20983 [](const detail::json_ref<basic_json>& element_ref)
20984 {
20985 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20986 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20987 // broken call to op[key_type], the wrong semantics, and a 4804 warning on Windows)
20988 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20989 });
20990
20991 // adjust type if type deduction is not wanted
20992 if (!type_deduction)
20993 {
20994 // if an array is wanted, do not create an object though possible
20995 if (manual_type == value_t::array)
20996 {
20997 is_an_object = false;
20998 }
20999
21000 // if an object is wanted but impossible, throw an exception
21001 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
21002 {
21003 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
21004 }
21005 }
21006
21007 if (is_an_object)
21008 {
21009 // the initializer list is a list of pairs -> create an object
21010 m_data.m_type = value_t::object;
21011 m_data.m_value = value_t::object;
21012
21013 for (auto& element_ref : init)
21014 {
21015 auto element = element_ref.moved_or_copied();
21016 m_data.m_value.object->emplace(
21017 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
21018 std::move((*element.m_data.m_value.array)[1]));
21019 }
21020 }
21021 else
21022 {
21023 // the initializer list describes an array -> create an array
21024 m_data.m_type = value_t::array;
21025 m_data.m_value.array = create<array_t>(init.begin(), init.end());
21026 }
21027
21028 set_parents();
21029 assert_invariant();
21030 }
21031
21035 static basic_json binary(const typename binary_t::container_type& init)
21036 {
21037 auto res = basic_json();
21038 res.m_data.m_type = value_t::binary;
21039 res.m_data.m_value = init;
21040 return res;
21041 }
21042
21046 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
21047 {
21048 auto res = basic_json();
21049 res.m_data.m_type = value_t::binary;
21050 res.m_data.m_value = binary_t(init, subtype);
21051 return res;
21052 }
21053
21057 static basic_json binary(typename binary_t::container_type&& init)
21058 {
21059 auto res = basic_json();
21060 res.m_data.m_type = value_t::binary;
21061 res.m_data.m_value = std::move(init);
21062 return res;
21063 }
21064
21068 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21069 {
21070 auto res = basic_json();
21071 res.m_data.m_type = value_t::binary;
21072 res.m_data.m_value = binary_t(std::move(init), subtype);
21073 return res;
21074 }
21075
21080 {
21081 return basic_json(init, false, value_t::array);
21082 }
21083
21088 {
21089 return basic_json(init, false, value_t::object);
21090 }
21091
21095 m_data{cnt, val}
21096 {
21097 set_parents();
21098 assert_invariant();
21099 }
21100
21103 template < class InputIT, typename std::enable_if <
21104 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21105 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21106 basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21107 {
21108 JSON_ASSERT(first.m_object != nullptr);
21109 JSON_ASSERT(last.m_object != nullptr);
21110
21111 // make sure the iterator fits the current value
21112 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21113 {
21114 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21115 }
21116
21117 // copy type from the first iterator
21118 m_data.m_type = first.m_object->m_data.m_type;
21119
21120 // check if the iterator range is complete for primitive values
21121 switch (m_data.m_type)
21122 {
21123 case value_t::boolean:
21124 case value_t::number_float:
21125 case value_t::number_integer:
21126 case value_t::number_unsigned:
21127 case value_t::string:
21128 {
21129 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21130 || !last.m_it.primitive_iterator.is_end()))
21131 {
21132 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21133 }
21134 break;
21135 }
21136
21137 case value_t::null:
21138 case value_t::object:
21139 case value_t::array:
21140 case value_t::binary:
21141 case value_t::discarded:
21142 default:
21143 break;
21144 }
21145
21146 switch (m_data.m_type)
21147 {
21148 case value_t::number_integer:
21149 {
21150 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21151 break;
21152 }
21153
21154 case value_t::number_unsigned:
21155 {
21156 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21157 break;
21158 }
21159
21160 case value_t::number_float:
21161 {
21162 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21163 break;
21164 }
21165
21166 case value_t::boolean:
21167 {
21168 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21169 break;
21170 }
21171
21172 case value_t::string:
21173 {
21174 m_data.m_value = *first.m_object->m_data.m_value.string;
21175 break;
21176 }
21177
21178 case value_t::object:
21179 {
21180 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21181 last.m_it.object_iterator);
21182 break;
21183 }
21184
21185 case value_t::array:
21186 {
21187 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21188 last.m_it.array_iterator);
21189 break;
21190 }
21191
21192 case value_t::binary:
21193 {
21194 m_data.m_value = *first.m_object->m_data.m_value.binary;
21195 break;
21196 }
21197
21198 case value_t::null:
21199 case value_t::discarded:
21200 default:
21201 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21202 }
21203
21204 set_parents();
21205 assert_invariant();
21206 }
21207
21209 // other constructors and destructor //
21211
21212 template<typename JsonRef,
21214 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21215 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21216
21220 : json_base_class_t(other)
21222 , start_position(other.start_position)
21223 , end_position(other.end_position)
21224#endif
21225 {
21226 m_data.m_type = other.m_data.m_type;
21227 // check of passed value is valid
21228 other.assert_invariant();
21229
21230 switch (m_data.m_type)
21231 {
21232 case value_t::object:
21233 {
21234 m_data.m_value = *other.m_data.m_value.object;
21235 break;
21236 }
21237
21238 case value_t::array:
21239 {
21240 m_data.m_value = *other.m_data.m_value.array;
21241 break;
21242 }
21243
21244 case value_t::string:
21245 {
21246 m_data.m_value = *other.m_data.m_value.string;
21247 break;
21248 }
21249
21250 case value_t::boolean:
21251 {
21252 m_data.m_value = other.m_data.m_value.boolean;
21253 break;
21254 }
21255
21256 case value_t::number_integer:
21257 {
21258 m_data.m_value = other.m_data.m_value.number_integer;
21259 break;
21260 }
21261
21262 case value_t::number_unsigned:
21263 {
21264 m_data.m_value = other.m_data.m_value.number_unsigned;
21265 break;
21266 }
21267
21268 case value_t::number_float:
21269 {
21270 m_data.m_value = other.m_data.m_value.number_float;
21271 break;
21272 }
21273
21274 case value_t::binary:
21275 {
21276 m_data.m_value = *other.m_data.m_value.binary;
21277 break;
21278 }
21279
21280 case value_t::null:
21281 case value_t::discarded:
21282 default:
21283 break;
21284 }
21285
21286 set_parents();
21287 assert_invariant();
21288 }
21289
21292 basic_json(basic_json&& other) noexcept
21293 : json_base_class_t(std::forward<json_base_class_t>(other)),
21294 m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21295#if JSON_DIAGNOSTIC_POSITIONS
21296 , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21297 , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21298#endif
21299 {
21300 // check that the passed value is valid
21301 other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21302
21303 // invalidate payload
21304 other.m_data.m_type = value_t::null;
21305 other.m_data.m_value = {};
21306
21307#if JSON_DIAGNOSTIC_POSITIONS
21308 other.start_position = std::string::npos;
21309 other.end_position = std::string::npos;
21310#endif
21311
21312 set_parents();
21313 assert_invariant();
21314 }
21315
21319 std::is_nothrow_move_constructible<value_t>::value&&
21320 std::is_nothrow_move_assignable<value_t>::value&&
21321 std::is_nothrow_move_constructible<json_value>::value&&
21322 std::is_nothrow_move_assignable<json_value>::value&&
21323 std::is_nothrow_move_assignable<json_base_class_t>::value
21324 )
21325 {
21326 // check that the passed value is valid
21327 other.assert_invariant();
21328
21329 using std::swap;
21330 swap(m_data.m_type, other.m_data.m_type);
21331 swap(m_data.m_value, other.m_data.m_value);
21332
21333#if JSON_DIAGNOSTIC_POSITIONS
21334 swap(start_position, other.start_position);
21335 swap(end_position, other.end_position);
21336#endif
21337
21338 json_base_class_t::operator=(std::move(other));
21339
21340 set_parents();
21341 assert_invariant();
21342 return *this;
21343 }
21344
21347 ~basic_json() noexcept
21348 {
21349 assert_invariant(false);
21350 }
21351
21353
21354 public:
21356 // object inspection //
21358
21362
21365 string_t dump(const int indent = -1,
21366 const char indent_char = ' ',
21367 const bool ensure_ascii = false,
21368 const error_handler_t error_handler = error_handler_t::strict) const
21369 {
21370 string_t result;
21371 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21372
21373 if (indent >= 0)
21374 {
21375 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21376 }
21377 else
21378 {
21379 s.dump(*this, false, ensure_ascii, 0);
21380 }
21381
21382 return result;
21383 }
21384
21387 constexpr value_t type() const noexcept
21388 {
21389 return m_data.m_type;
21390 }
21391
21394 constexpr bool is_primitive() const noexcept
21395 {
21396 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21397 }
21398
21401 constexpr bool is_structured() const noexcept
21402 {
21403 return is_array() || is_object();
21404 }
21405
21408 constexpr bool is_null() const noexcept
21409 {
21410 return m_data.m_type == value_t::null;
21411 }
21412
21415 constexpr bool is_boolean() const noexcept
21416 {
21417 return m_data.m_type == value_t::boolean;
21418 }
21419
21422 constexpr bool is_number() const noexcept
21423 {
21424 return is_number_integer() || is_number_float();
21425 }
21426
21429 constexpr bool is_number_integer() const noexcept
21430 {
21431 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21432 }
21433
21436 constexpr bool is_number_unsigned() const noexcept
21437 {
21438 return m_data.m_type == value_t::number_unsigned;
21439 }
21440
21443 constexpr bool is_number_float() const noexcept
21444 {
21445 return m_data.m_type == value_t::number_float;
21446 }
21447
21450 constexpr bool is_object() const noexcept
21451 {
21452 return m_data.m_type == value_t::object;
21453 }
21454
21457 constexpr bool is_array() const noexcept
21458 {
21459 return m_data.m_type == value_t::array;
21460 }
21461
21464 constexpr bool is_string() const noexcept
21465 {
21466 return m_data.m_type == value_t::string;
21467 }
21468
21471 constexpr bool is_binary() const noexcept
21472 {
21473 return m_data.m_type == value_t::binary;
21474 }
21475
21478 constexpr bool is_discarded() const noexcept
21479 {
21480 return m_data.m_type == value_t::discarded;
21481 }
21482
21485 constexpr operator value_t() const noexcept
21486 {
21487 return m_data.m_type;
21488 }
21489
21491
21492 private:
21494 // value access //
21496
21498 boolean_t get_impl(boolean_t* /*unused*/) const
21499 {
21500 if (JSON_HEDLEY_LIKELY(is_boolean()))
21501 {
21502 return m_data.m_value.boolean;
21503 }
21504
21505 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21506 }
21507
21509 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21510 {
21511 return is_object() ? m_data.m_value.object : nullptr;
21512 }
21513
21515 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21516 {
21517 return is_object() ? m_data.m_value.object : nullptr;
21518 }
21519
21521 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21522 {
21523 return is_array() ? m_data.m_value.array : nullptr;
21524 }
21525
21527 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21528 {
21529 return is_array() ? m_data.m_value.array : nullptr;
21530 }
21531
21533 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21534 {
21535 return is_string() ? m_data.m_value.string : nullptr;
21536 }
21537
21539 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21540 {
21541 return is_string() ? m_data.m_value.string : nullptr;
21542 }
21543
21545 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21546 {
21547 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21548 }
21549
21551 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21552 {
21553 return is_boolean() ? &m_data.m_value.boolean : nullptr;
21554 }
21555
21557 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
21558 {
21559 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21560 }
21561
21563 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21564 {
21565 return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21566 }
21567
21569 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
21570 {
21571 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21572 }
21573
21575 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21576 {
21577 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21578 }
21579
21581 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
21582 {
21583 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21584 }
21585
21587 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21588 {
21589 return is_number_float() ? &m_data.m_value.number_float : nullptr;
21590 }
21591
21593 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21594 {
21595 return is_binary() ? m_data.m_value.binary : nullptr;
21596 }
21597
21599 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21600 {
21601 return is_binary() ? m_data.m_value.binary : nullptr;
21602 }
21603
21615 template<typename ReferenceType, typename ThisType>
21616 static ReferenceType get_ref_impl(ThisType& obj)
21617 {
21618 // delegate the call to get_ptr<>()
21619 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21620
21621 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21622 {
21623 return *ptr;
21624 }
21625
21626 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21627 }
21628
21629 public:
21633
21636 template<typename PointerType, typename std::enable_if<
21637 std::is_pointer<PointerType>::value, int>::type = 0>
21638 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21639 {
21640 // delegate the call to get_impl_ptr<>()
21641 return get_impl_ptr(static_cast<PointerType>(nullptr));
21642 }
21643
21646 template < typename PointerType, typename std::enable_if <
21647 std::is_pointer<PointerType>::value&&
21648 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21649 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21650 {
21651 // delegate the call to get_impl_ptr<>() const
21652 return get_impl_ptr(static_cast<PointerType>(nullptr));
21653 }
21654
21655 private:
21694 template < typename ValueType,
21698 int > = 0 >
21699 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21700 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21701 {
21702 auto ret = ValueType();
21703 JSONSerializer<ValueType>::from_json(*this, ret);
21704 return ret;
21705 }
21706
21737 template < typename ValueType,
21739 detail::has_non_default_from_json<basic_json_t, ValueType>::value,
21740 int > = 0 >
21741 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21742 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21743 {
21744 return JSONSerializer<ValueType>::from_json(*this);
21745 }
21746
21762 template < typename BasicJsonType,
21764 detail::is_basic_json<BasicJsonType>::value,
21765 int > = 0 >
21766 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21767 {
21768 return *this;
21769 }
21770
21785 template<typename BasicJsonType,
21787 std::is_same<BasicJsonType, basic_json_t>::value,
21788 int> = 0>
21789 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21790 {
21791 return *this;
21792 }
21793
21798 template<typename PointerType,
21800 std::is_pointer<PointerType>::value,
21801 int> = 0>
21802 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21803 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21804 {
21805 // delegate the call to get_ptr
21806 return get_ptr<PointerType>();
21807 }
21808
21809 public:
21833 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21834#if defined(JSON_HAS_CPP_14)
21835 constexpr
21836#endif
21837 auto get() const noexcept(
21838 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21839 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21840 {
21841 // we cannot static_assert on ValueTypeCV being non-const, because
21842 // there is support for get<const basic_json_t>(), which is why we
21843 // still need the uncvref
21844 static_assert(!std::is_reference<ValueTypeCV>::value,
21845 "get() cannot be used with reference types, you might want to use get_ref()");
21846 return get_impl<ValueType>(detail::priority_tag<4> {});
21847 }
21848
21876 template<typename PointerType, typename std::enable_if<
21877 std::is_pointer<PointerType>::value, int>::type = 0>
21878 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21879 {
21880 // delegate the call to get_ptr
21881 return get_ptr<PointerType>();
21882 }
21883
21886 template < typename ValueType,
21890 int > = 0 >
21891 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21892 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21893 {
21894 JSONSerializer<ValueType>::from_json(*this, v);
21895 return v;
21896 }
21897
21898 // specialization to allow calling get_to with a basic_json value
21899 // see https://github.com/nlohmann/json/issues/2175
21900 template<typename ValueType,
21903 int> = 0>
21904 ValueType & get_to(ValueType& v) const
21905 {
21906 v = *this;
21907 return v;
21908 }
21909
21910 template <
21911 typename T, std::size_t N,
21912 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21915 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21916 noexcept(noexcept(JSONSerializer<Array>::from_json(
21917 std::declval<const basic_json_t&>(), v)))
21918 {
21919 JSONSerializer<Array>::from_json(*this, v);
21920 return v;
21921 }
21922
21925 template<typename ReferenceType, typename std::enable_if<
21926 std::is_reference<ReferenceType>::value, int>::type = 0>
21927 ReferenceType get_ref()
21928 {
21929 // delegate call to get_ref_impl
21930 return get_ref_impl<ReferenceType>(*this);
21931 }
21932
21935 template < typename ReferenceType, typename std::enable_if <
21936 std::is_reference<ReferenceType>::value&&
21937 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21938 ReferenceType get_ref() const
21939 {
21940 // delegate call to get_ref_impl
21941 return get_ref_impl<ReferenceType>(*this);
21942 }
21943
21973 template < typename ValueType, typename std::enable_if <
21981#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21983#endif
21984#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21986#endif
21988 >::value, int >::type = 0 >
21989 JSON_EXPLICIT operator ValueType() const
21990 {
21991 // delegate the call to get<>() const
21992 return get<ValueType>();
21993 }
21994
21998 {
21999 if (!is_binary())
22000 {
22001 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22002 }
22003
22004 return *get_ptr<binary_t*>();
22005 }
22006
22009 const binary_t& get_binary() const
22010 {
22011 if (!is_binary())
22012 {
22013 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
22014 }
22015
22016 return *get_ptr<const binary_t*>();
22017 }
22018
22020
22022 // element access //
22024
22028
22032 {
22033 // at only works for arrays
22035 {
22036 JSON_TRY
22037 {
22038 return set_parent(m_data.m_value.array->at(idx));
22039 }
22040 JSON_CATCH (std::out_of_range&)
22041 {
22042 // create a better exception explanation
22043 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22044 } // cppcheck-suppress[missingReturn]
22045 }
22046 else
22047 {
22048 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22049 }
22050 }
22051
22055 {
22056 // at only works for arrays
22058 {
22059 JSON_TRY
22060 {
22061 return m_data.m_value.array->at(idx);
22062 }
22063 JSON_CATCH (std::out_of_range&)
22064 {
22065 // create a better exception explanation
22066 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22067 } // cppcheck-suppress[missingReturn]
22068 }
22069 else
22070 {
22071 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22072 }
22073 }
22074
22077 reference at(const typename object_t::key_type& key)
22078 {
22079 // at only works for objects
22081 {
22082 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22083 }
22084
22085 auto it = m_data.m_value.object->find(key);
22086 if (it == m_data.m_value.object->end())
22087 {
22088 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22089 }
22090 return set_parent(it->second);
22091 }
22092
22095 template<class KeyType, detail::enable_if_t<
22097 reference at(KeyType && key)
22098 {
22099 // at only works for objects
22101 {
22102 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22103 }
22104
22105 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22106 if (it == m_data.m_value.object->end())
22107 {
22108 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22109 }
22110 return set_parent(it->second);
22111 }
22112
22115 const_reference at(const typename object_t::key_type& key) const
22116 {
22117 // at only works for objects
22119 {
22120 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22121 }
22122
22123 auto it = m_data.m_value.object->find(key);
22124 if (it == m_data.m_value.object->end())
22125 {
22126 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22127 }
22128 return it->second;
22129 }
22130
22133 template<class KeyType, detail::enable_if_t<
22135 const_reference at(KeyType && key) const
22136 {
22137 // at only works for objects
22139 {
22140 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22141 }
22142
22143 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22144 if (it == m_data.m_value.object->end())
22145 {
22146 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22147 }
22148 return it->second;
22149 }
22150
22154 {
22155 // implicitly convert a null value to an empty array
22156 if (is_null())
22157 {
22158 m_data.m_type = value_t::array;
22159 m_data.m_value.array = create<array_t>();
22160 assert_invariant();
22161 }
22162
22163 // operator[] only works for arrays
22165 {
22166 // fill up the array with null values if given idx is outside the range
22167 if (idx >= m_data.m_value.array->size())
22168 {
22169#if JSON_DIAGNOSTICS
22170 // remember array size & capacity before resizing
22171 const auto old_size = m_data.m_value.array->size();
22172 const auto old_capacity = m_data.m_value.array->capacity();
22173#endif
22174 m_data.m_value.array->resize(idx + 1);
22175
22176#if JSON_DIAGNOSTICS
22177 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22178 {
22179 // capacity has changed: update all parents
22180 set_parents();
22181 }
22182 else
22183 {
22184 // set parent for values added above
22185 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22186 }
22187#endif
22188 assert_invariant();
22189 }
22190
22191 return m_data.m_value.array->operator[](idx);
22192 }
22193
22194 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22195 }
22196
22200 {
22201 // const operator[] only works for arrays
22203 {
22204 return m_data.m_value.array->operator[](idx);
22205 }
22206
22207 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22208 }
22209
22212 reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22213 {
22214 // implicitly convert a null value to an empty object
22215 if (is_null())
22216 {
22217 m_data.m_type = value_t::object;
22218 m_data.m_value.object = create<object_t>();
22219 assert_invariant();
22220 }
22221
22222 // operator[] only works for objects
22224 {
22225 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22226 return set_parent(result.first->second);
22227 }
22228
22229 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22230 }
22231
22234 const_reference operator[](const typename object_t::key_type& key) const
22235 {
22236 // const operator[] only works for objects
22238 {
22239 auto it = m_data.m_value.object->find(key);
22240 JSON_ASSERT(it != m_data.m_value.object->end());
22241 return it->second;
22242 }
22243
22244 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22245 }
22246
22247 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22248 // (they seemingly cannot be constrained to resolve the ambiguity)
22249 template<typename T>
22251 {
22252 return operator[](typename object_t::key_type(key));
22253 }
22254
22255 template<typename T>
22257 {
22258 return operator[](typename object_t::key_type(key));
22259 }
22260
22263 template<class KeyType, detail::enable_if_t<
22266 {
22267 // implicitly convert a null value to an empty object
22268 if (is_null())
22269 {
22270 m_data.m_type = value_t::object;
22271 m_data.m_value.object = create<object_t>();
22272 assert_invariant();
22273 }
22274
22275 // operator[] only works for objects
22277 {
22278 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22279 return set_parent(result.first->second);
22280 }
22281
22282 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22283 }
22284
22287 template<class KeyType, detail::enable_if_t<
22290 {
22291 // const operator[] only works for objects
22293 {
22294 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22295 JSON_ASSERT(it != m_data.m_value.object->end());
22296 return it->second;
22297 }
22298
22299 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22300 }
22301
22302 private:
22303 template<typename KeyType>
22304 using is_comparable_with_object_key = detail::is_comparable <
22305 object_comparator_t, const typename object_t::key_type&, KeyType >;
22306
22307 template<typename ValueType>
22308 using value_return_type = std::conditional <
22310 string_t, typename std::decay<ValueType>::type >;
22311
22312 public:
22315 template < class ValueType, detail::enable_if_t <
22318 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22319 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22320 {
22321 // value only works for objects
22323 {
22324 // If 'key' is found, return its value. Otherwise, return `default_value'.
22325 const auto it = find(key);
22326 if (it != end())
22327 {
22328 return it->template get<ValueType>();
22329 }
22330
22331 return default_value;
22332 }
22333
22334 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22335 }
22336
22339 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22343 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22344 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22345 {
22346 // value only works for objects
22348 {
22349 // If 'key' is found, return its value. Otherwise, return `default_value'.
22350 const auto it = find(key);
22351 if (it != end())
22352 {
22353 return it->template get<ReturnType>();
22354 }
22355
22356 return std::forward<ValueType>(default_value);
22357 }
22358
22359 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22360 }
22361
22364 template < class ValueType, class KeyType, detail::enable_if_t <
22367 && is_comparable_with_object_key<KeyType>::value
22369 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22370 ValueType value(KeyType && key, const ValueType& default_value) const
22371 {
22372 // value only works for objects
22374 {
22375 // If 'key' is found, return its value. Otherwise, return `default_value'.
22376 const auto it = find(std::forward<KeyType>(key));
22377 if (it != end())
22378 {
22379 return it->template get<ValueType>();
22380 }
22381
22382 return default_value;
22383 }
22384
22385 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22386 }
22387
22390 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22394 && is_comparable_with_object_key<KeyType>::value
22396 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22397 ReturnType value(KeyType && key, ValueType && default_value) const
22398 {
22399 // value only works for objects
22401 {
22402 // If 'key' is found, return its value. Otherwise, return `default_value'.
22403 const auto it = find(std::forward<KeyType>(key));
22404 if (it != end())
22405 {
22406 return it->template get<ReturnType>();
22407 }
22408
22409 return std::forward<ValueType>(default_value);
22410 }
22411
22412 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22413 }
22414
22417 template < class ValueType, detail::enable_if_t <
22419 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22420 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22421 {
22422 // value only works for objects
22424 {
22425 // If the pointer resolves to a value, return it. Otherwise, return
22426 // 'default_value'.
22427 JSON_TRY
22428 {
22429 return ptr.get_checked(this).template get<ValueType>();
22430 }
22432 {
22433 return default_value;
22434 }
22435 }
22436
22437 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22438 }
22439
22442 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22445 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22446 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22447 {
22448 // value only works for objects
22450 {
22451 // If the pointer resolves to a value, return it. Otherwise, return
22452 // 'default_value'.
22453 JSON_TRY
22454 {
22455 return ptr.get_checked(this).template get<ReturnType>();
22456 }
22458 {
22459 return std::forward<ValueType>(default_value);
22460 }
22461 }
22462
22463 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22464 }
22465
22466 template < class ValueType, class BasicJsonType, detail::enable_if_t <
22469 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22470 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22471 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22472 {
22473 return value(ptr.convert(), default_value);
22474 }
22475
22476 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22480 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22481 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22482 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22483 {
22484 return value(ptr.convert(), std::forward<ValueType>(default_value));
22485 }
22486
22490 {
22491 return *begin();
22492 }
22493
22497 {
22498 return *cbegin();
22499 }
22500
22504 {
22505 auto tmp = end();
22506 --tmp;
22507 return *tmp;
22508 }
22509
22513 {
22514 auto tmp = cend();
22515 --tmp;
22516 return *tmp;
22517 }
22518
22521 template < class IteratorType, detail::enable_if_t <
22522 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22523 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22524 IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22525 {
22526 // make sure the iterator fits the current value
22527 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22528 {
22529 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22530 }
22531
22532 IteratorType result = end();
22533
22534 switch (m_data.m_type)
22535 {
22536 case value_t::boolean:
22537 case value_t::number_float:
22538 case value_t::number_integer:
22539 case value_t::number_unsigned:
22540 case value_t::string:
22541 case value_t::binary:
22542 {
22543 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22544 {
22545 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22546 }
22547
22548 if (is_string())
22549 {
22550 AllocatorType<string_t> alloc;
22551 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22552 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22553 m_data.m_value.string = nullptr;
22554 }
22555 else if (is_binary())
22556 {
22557 AllocatorType<binary_t> alloc;
22558 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22559 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22560 m_data.m_value.binary = nullptr;
22561 }
22562
22563 m_data.m_type = value_t::null;
22564 assert_invariant();
22565 break;
22566 }
22567
22568 case value_t::object:
22569 {
22570 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22571 break;
22572 }
22573
22574 case value_t::array:
22575 {
22576 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22577 break;
22578 }
22579
22580 case value_t::null:
22581 case value_t::discarded:
22582 default:
22583 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22584 }
22585
22586 return result;
22587 }
22588
22591 template < class IteratorType, detail::enable_if_t <
22592 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22593 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22594 IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22595 {
22596 // make sure the iterator fits the current value
22597 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22598 {
22599 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22600 }
22601
22602 IteratorType result = end();
22603
22604 switch (m_data.m_type)
22605 {
22606 case value_t::boolean:
22607 case value_t::number_float:
22608 case value_t::number_integer:
22609 case value_t::number_unsigned:
22610 case value_t::string:
22611 case value_t::binary:
22612 {
22613 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22614 || !last.m_it.primitive_iterator.is_end()))
22615 {
22616 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22617 }
22618
22619 if (is_string())
22620 {
22621 AllocatorType<string_t> alloc;
22622 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22623 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22624 m_data.m_value.string = nullptr;
22625 }
22626 else if (is_binary())
22627 {
22628 AllocatorType<binary_t> alloc;
22629 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22630 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22631 m_data.m_value.binary = nullptr;
22632 }
22633
22634 m_data.m_type = value_t::null;
22635 assert_invariant();
22636 break;
22637 }
22638
22639 case value_t::object:
22640 {
22641 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22642 last.m_it.object_iterator);
22643 break;
22644 }
22645
22646 case value_t::array:
22647 {
22648 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22649 last.m_it.array_iterator);
22650 break;
22651 }
22652
22653 case value_t::null:
22654 case value_t::discarded:
22655 default:
22656 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22657 }
22658
22659 return result;
22660 }
22661
22662 private:
22663 template < typename KeyType, detail::enable_if_t <
22665 size_type erase_internal(KeyType && key)
22666 {
22667 // this erase only works for objects
22668 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22669 {
22670 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22671 }
22672
22673 return m_data.m_value.object->erase(std::forward<KeyType>(key));
22674 }
22675
22676 template < typename KeyType, detail::enable_if_t <
22677 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22678 size_type erase_internal(KeyType && key)
22679 {
22680 // this erase only works for objects
22681 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22682 {
22683 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22684 }
22685
22686 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22687 if (it != m_data.m_value.object->end())
22688 {
22689 m_data.m_value.object->erase(it);
22690 return 1;
22691 }
22692 return 0;
22693 }
22694
22695 public:
22696
22699 size_type erase(const typename object_t::key_type& key)
22700 {
22701 // the indirection via erase_internal() is added to avoid making this
22702 // function a template and thus de-rank it during overload resolution
22703 return erase_internal(key);
22704 }
22705
22708 template<class KeyType, detail::enable_if_t<
22710 size_type erase(KeyType && key)
22711 {
22712 return erase_internal(std::forward<KeyType>(key));
22713 }
22714
22717 void erase(const size_type idx)
22718 {
22719 // this erase only works for arrays
22721 {
22722 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22723 {
22724 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22725 }
22726
22727 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22728 }
22729 else
22730 {
22731 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22732 }
22733 }
22734
22736
22738 // lookup //
22740
22743
22746 iterator find(const typename object_t::key_type& key)
22747 {
22748 auto result = end();
22749
22750 if (is_object())
22751 {
22752 result.m_it.object_iterator = m_data.m_value.object->find(key);
22753 }
22754
22755 return result;
22756 }
22757
22760 const_iterator find(const typename object_t::key_type& key) const
22761 {
22762 auto result = cend();
22763
22764 if (is_object())
22765 {
22766 result.m_it.object_iterator = m_data.m_value.object->find(key);
22767 }
22768
22769 return result;
22770 }
22771
22774 template<class KeyType, detail::enable_if_t<
22776 iterator find(KeyType && key)
22777 {
22778 auto result = end();
22779
22780 if (is_object())
22781 {
22782 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22783 }
22784
22785 return result;
22786 }
22787
22790 template<class KeyType, detail::enable_if_t<
22792 const_iterator find(KeyType && key) const
22793 {
22794 auto result = cend();
22795
22796 if (is_object())
22797 {
22798 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22799 }
22800
22801 return result;
22802 }
22803
22806 size_type count(const typename object_t::key_type& key) const
22807 {
22808 // return 0 for all nonobject types
22809 return is_object() ? m_data.m_value.object->count(key) : 0;
22810 }
22811
22814 template<class KeyType, detail::enable_if_t<
22816 size_type count(KeyType && key) const
22817 {
22818 // return 0 for all nonobject types
22819 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22820 }
22821
22824 bool contains(const typename object_t::key_type& key) const
22825 {
22826 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22827 }
22828
22831 template<class KeyType, detail::enable_if_t<
22833 bool contains(KeyType && key) const
22834 {
22835 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22836 }
22837
22840 bool contains(const json_pointer& ptr) const
22841 {
22842 return ptr.contains(this);
22843 }
22844
22845 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22846 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22847 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22848 {
22849 return ptr.contains(this);
22850 }
22851
22853
22855 // iterators //
22857
22860
22863 iterator begin() noexcept
22864 {
22865 iterator result(this);
22866 result.set_begin();
22867 return result;
22868 }
22869
22872 const_iterator begin() const noexcept
22873 {
22874 return cbegin();
22875 }
22876
22879 const_iterator cbegin() const noexcept
22880 {
22881 const_iterator result(this);
22882 result.set_begin();
22883 return result;
22884 }
22885
22888 iterator end() noexcept
22889 {
22890 iterator result(this);
22891 result.set_end();
22892 return result;
22893 }
22894
22897 const_iterator end() const noexcept
22898 {
22899 return cend();
22900 }
22901
22904 const_iterator cend() const noexcept
22905 {
22906 const_iterator result(this);
22907 result.set_end();
22908 return result;
22909 }
22910
22914 {
22915 return reverse_iterator(end());
22916 }
22917
22921 {
22922 return crbegin();
22923 }
22924
22928 {
22929 return reverse_iterator(begin());
22930 }
22931
22935 {
22936 return crend();
22937 }
22938
22942 {
22943 return const_reverse_iterator(cend());
22944 }
22945
22949 {
22951 }
22952
22953 public:
22959 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22960 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22961 {
22962 return ref.items();
22963 }
22964
22970 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22971 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22972 {
22973 return ref.items();
22974 }
22975
22978 iteration_proxy<iterator> items() noexcept
22979 {
22980 return iteration_proxy<iterator>(*this);
22981 }
22982
22985 iteration_proxy<const_iterator> items() const noexcept
22986 {
22987 return iteration_proxy<const_iterator>(*this);
22988 }
22989
22991
22993 // capacity //
22995
22998
23001 bool empty() const noexcept
23002 {
23003 switch (m_data.m_type)
23004 {
23005 case value_t::null:
23006 {
23007 // null values are empty
23008 return true;
23009 }
23010
23011 case value_t::array:
23012 {
23013 // delegate call to array_t::empty()
23014 return m_data.m_value.array->empty();
23015 }
23016
23017 case value_t::object:
23018 {
23019 // delegate call to object_t::empty()
23020 return m_data.m_value.object->empty();
23021 }
23022
23023 case value_t::string:
23024 case value_t::boolean:
23025 case value_t::number_integer:
23026 case value_t::number_unsigned:
23027 case value_t::number_float:
23028 case value_t::binary:
23029 case value_t::discarded:
23030 default:
23031 {
23032 // all other types are nonempty
23033 return false;
23034 }
23035 }
23036 }
23037
23040 size_type size() const noexcept
23041 {
23042 switch (m_data.m_type)
23043 {
23044 case value_t::null:
23045 {
23046 // null values are empty
23047 return 0;
23048 }
23049
23050 case value_t::array:
23051 {
23052 // delegate call to array_t::size()
23053 return m_data.m_value.array->size();
23054 }
23055
23056 case value_t::object:
23057 {
23058 // delegate call to object_t::size()
23059 return m_data.m_value.object->size();
23060 }
23061
23062 case value_t::string:
23063 case value_t::boolean:
23064 case value_t::number_integer:
23065 case value_t::number_unsigned:
23066 case value_t::number_float:
23067 case value_t::binary:
23068 case value_t::discarded:
23069 default:
23070 {
23071 // all other types have size 1
23072 return 1;
23073 }
23074 }
23075 }
23076
23079 size_type max_size() const noexcept
23080 {
23081 switch (m_data.m_type)
23082 {
23083 case value_t::array:
23084 {
23085 // delegate call to array_t::max_size()
23086 return m_data.m_value.array->max_size();
23087 }
23088
23089 case value_t::object:
23090 {
23091 // delegate call to object_t::max_size()
23092 return m_data.m_value.object->max_size();
23093 }
23094
23095 case value_t::null:
23096 case value_t::string:
23097 case value_t::boolean:
23098 case value_t::number_integer:
23099 case value_t::number_unsigned:
23100 case value_t::number_float:
23101 case value_t::binary:
23102 case value_t::discarded:
23103 default:
23104 {
23105 // all other types have max_size() == size()
23106 return size();
23107 }
23108 }
23109 }
23110
23112
23114 // modifiers //
23116
23119
23122 void clear() noexcept
23123 {
23124 switch (m_data.m_type)
23125 {
23126 case value_t::number_integer:
23127 {
23128 m_data.m_value.number_integer = 0;
23129 break;
23130 }
23131
23132 case value_t::number_unsigned:
23133 {
23134 m_data.m_value.number_unsigned = 0;
23135 break;
23136 }
23137
23138 case value_t::number_float:
23139 {
23140 m_data.m_value.number_float = 0.0;
23141 break;
23142 }
23143
23144 case value_t::boolean:
23145 {
23146 m_data.m_value.boolean = false;
23147 break;
23148 }
23149
23150 case value_t::string:
23151 {
23152 m_data.m_value.string->clear();
23153 break;
23154 }
23155
23156 case value_t::binary:
23157 {
23158 m_data.m_value.binary->clear();
23159 break;
23160 }
23161
23162 case value_t::array:
23163 {
23164 m_data.m_value.array->clear();
23165 break;
23166 }
23167
23168 case value_t::object:
23169 {
23170 m_data.m_value.object->clear();
23171 break;
23172 }
23173
23174 case value_t::null:
23175 case value_t::discarded:
23176 default:
23177 break;
23178 }
23179 }
23180
23184 {
23185 // push_back only works for null objects or arrays
23186 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23187 {
23188 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23189 }
23190
23191 // transform a null object into an array
23192 if (is_null())
23193 {
23194 m_data.m_type = value_t::array;
23195 m_data.m_value = value_t::array;
23196 assert_invariant();
23197 }
23198
23199 // add the element to the array (move semantics)
23200 const auto old_capacity = m_data.m_value.array->capacity();
23201 m_data.m_value.array->push_back(std::move(val));
23202 set_parent(m_data.m_value.array->back(), old_capacity);
23203 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23204 }
23205
23209 {
23210 push_back(std::move(val));
23211 return *this;
23212 }
23213
23216 void push_back(const basic_json& val)
23217 {
23218 // push_back only works for null objects or arrays
23219 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23220 {
23221 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23222 }
23223
23224 // transform a null object into an array
23225 if (is_null())
23226 {
23227 m_data.m_type = value_t::array;
23228 m_data.m_value = value_t::array;
23229 assert_invariant();
23230 }
23231
23232 // add the element to the array
23233 const auto old_capacity = m_data.m_value.array->capacity();
23234 m_data.m_value.array->push_back(val);
23235 set_parent(m_data.m_value.array->back(), old_capacity);
23236 }
23237
23241 {
23242 push_back(val);
23243 return *this;
23244 }
23245
23248 void push_back(const typename object_t::value_type& val)
23249 {
23250 // push_back only works for null objects or objects
23251 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23252 {
23253 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23254 }
23255
23256 // transform a null object into an object
23257 if (is_null())
23258 {
23259 m_data.m_type = value_t::object;
23260 m_data.m_value = value_t::object;
23261 assert_invariant();
23262 }
23263
23264 // add the element to the object
23265 auto res = m_data.m_value.object->insert(val);
23266 set_parent(res.first->second);
23267 }
23268
23271 reference operator+=(const typename object_t::value_type& val)
23272 {
23273 push_back(val);
23274 return *this;
23275 }
23276
23280 {
23281 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23282 {
23283 basic_json&& key = init.begin()->moved_or_copied();
23284 push_back(typename object_t::value_type(
23285 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23286 }
23287 else
23288 {
23289 push_back(basic_json(init));
23290 }
23291 }
23292
23296 {
23297 push_back(init);
23298 return *this;
23299 }
23300
23303 template<class... Args>
23304 reference emplace_back(Args&& ... args)
23305 {
23306 // emplace_back only works for null objects or arrays
23307 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23308 {
23309 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23310 }
23311
23312 // transform a null object into an array
23313 if (is_null())
23314 {
23315 m_data.m_type = value_t::array;
23316 m_data.m_value = value_t::array;
23317 assert_invariant();
23318 }
23319
23320 // add the element to the array (perfect forwarding)
23321 const auto old_capacity = m_data.m_value.array->capacity();
23322 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23323 return set_parent(m_data.m_value.array->back(), old_capacity);
23324 }
23325
23328 template<class... Args>
23329 std::pair<iterator, bool> emplace(Args&& ... args)
23330 {
23331 // emplace only works for null objects or arrays
23332 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23333 {
23334 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23335 }
23336
23337 // transform a null object into an object
23338 if (is_null())
23339 {
23340 m_data.m_type = value_t::object;
23341 m_data.m_value = value_t::object;
23342 assert_invariant();
23343 }
23344
23345 // add the element to the array (perfect forwarding)
23346 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23347 set_parent(res.first->second);
23348
23349 // create a result iterator and set iterator to the result of emplace
23350 auto it = begin();
23351 it.m_it.object_iterator = res.first;
23352
23353 // return pair of iterator and boolean
23354 return {it, res.second};
23355 }
23356
23360 template<typename... Args>
23361 iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23362 {
23363 iterator result(this);
23364 JSON_ASSERT(m_data.m_value.array != nullptr);
23365
23366 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23367 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23368 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23369
23370 // This could have been written as:
23371 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23372 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23373
23374 set_parents();
23375 return result;
23376 }
23377
23380 iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23381 {
23382 // insert only works for arrays
23384 {
23385 // check if iterator pos fits to this JSON value
23386 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23387 {
23388 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23389 }
23390
23391 // insert to array and return iterator
23392 return insert_iterator(pos, val);
23393 }
23394
23395 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23396 }
23397
23400 iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23401 {
23402 return insert(pos, val);
23403 }
23404
23407 iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23408 {
23409 // insert only works for arrays
23411 {
23412 // check if iterator pos fits to this JSON value
23413 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23414 {
23415 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23416 }
23417
23418 // insert to array and return iterator
23419 return insert_iterator(pos, cnt, val);
23420 }
23421
23422 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23423 }
23424
23427 iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23428 {
23429 // insert only works for arrays
23431 {
23432 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23433 }
23434
23435 // check if iterator pos fits to this JSON value
23436 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23437 {
23438 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23439 }
23440
23441 // check if range iterators belong to the same JSON object
23442 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23443 {
23444 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23445 }
23446
23447 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23448 {
23449 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23450 }
23451
23452 // insert to array and return iterator
23453 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23454 }
23455
23458 iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23459 {
23460 // insert only works for arrays
23462 {
23463 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23464 }
23465
23466 // check if iterator pos fits to this JSON value
23467 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23468 {
23469 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23470 }
23471
23472 // insert to array and return iterator
23473 return insert_iterator(pos, ilist.begin(), ilist.end());
23474 }
23475
23478 void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23479 {
23480 // insert only works for objects
23482 {
23483 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23484 }
23485
23486 // check if range iterators belong to the same JSON object
23487 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23488 {
23489 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23490 }
23491
23492 // passed iterators must belong to objects
23493 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23494 {
23495 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23496 }
23497
23498 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23499 set_parents();
23500 }
23501
23504 void update(const_reference j, bool merge_objects = false)
23505 {
23506 update(j.begin(), j.end(), merge_objects);
23507 }
23508
23511 void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23512 {
23513 // implicitly convert a null value to an empty object
23514 if (is_null())
23515 {
23516 m_data.m_type = value_t::object;
23517 m_data.m_value.object = create<object_t>();
23518 assert_invariant();
23519 }
23520
23522 {
23523 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23524 }
23525
23526 // check if range iterators belong to the same JSON object
23527 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23528 {
23529 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23530 }
23531
23532 // passed iterators must belong to objects
23533 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23534 {
23535 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23536 }
23537
23538 for (auto it = first; it != last; ++it)
23539 {
23540 if (merge_objects && it.value().is_object())
23541 {
23542 auto it2 = m_data.m_value.object->find(it.key());
23543 if (it2 != m_data.m_value.object->end())
23544 {
23545 it2->second.update(it.value(), true);
23546 continue;
23547 }
23548 }
23549 m_data.m_value.object->operator[](it.key()) = it.value();
23550#if JSON_DIAGNOSTICS
23551 m_data.m_value.object->operator[](it.key()).m_parent = this;
23552#endif
23553 }
23554 }
23555
23558 void swap(reference other) noexcept (
23559 std::is_nothrow_move_constructible<value_t>::value&&
23560 std::is_nothrow_move_assignable<value_t>::value&&
23561 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23562 std::is_nothrow_move_assignable<json_value>::value
23563 )
23564 {
23565 std::swap(m_data.m_type, other.m_data.m_type);
23566 std::swap(m_data.m_value, other.m_data.m_value);
23567
23568 set_parents();
23569 other.set_parents();
23570 assert_invariant();
23571 }
23572
23575 friend void swap(reference left, reference right) noexcept (
23576 std::is_nothrow_move_constructible<value_t>::value&&
23577 std::is_nothrow_move_assignable<value_t>::value&&
23578 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23579 std::is_nothrow_move_assignable<json_value>::value
23580 )
23581 {
23582 left.swap(right);
23583 }
23584
23587 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23588 {
23589 // swap only works for arrays
23591 {
23592 using std::swap;
23593 swap(*(m_data.m_value.array), other);
23594 }
23595 else
23596 {
23597 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23598 }
23599 }
23600
23603 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23604 {
23605 // swap only works for objects
23607 {
23608 using std::swap;
23609 swap(*(m_data.m_value.object), other);
23610 }
23611 else
23612 {
23613 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23614 }
23615 }
23616
23619 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23620 {
23621 // swap only works for strings
23623 {
23624 using std::swap;
23625 swap(*(m_data.m_value.string), other);
23626 }
23627 else
23628 {
23629 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23630 }
23631 }
23632
23635 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23636 {
23637 // swap only works for strings
23639 {
23640 using std::swap;
23641 swap(*(m_data.m_value.binary), other);
23642 }
23643 else
23644 {
23645 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23646 }
23647 }
23648
23651 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23652 {
23653 // swap only works for strings
23655 {
23656 using std::swap;
23657 swap(*(m_data.m_value.binary), other);
23658 }
23659 else
23660 {
23661 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23662 }
23663 }
23664
23666
23668 // lexicographical comparison operators //
23670
23673
23674 // note parentheses around operands are necessary; see
23675 // https://github.com/nlohmann/json/issues/1530
23676#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
23677 const auto lhs_type = lhs.type(); \
23678 const auto rhs_type = rhs.type(); \
23679 \
23680 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
23681 { \
23682 switch (lhs_type) \
23683 { \
23684 case value_t::array: \
23685 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
23686 \
23687 case value_t::object: \
23688 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
23689 \
23690 case value_t::null: \
23691 return (null_result); \
23692 \
23693 case value_t::string: \
23694 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
23695 \
23696 case value_t::boolean: \
23697 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
23698 \
23699 case value_t::number_integer: \
23700 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
23701 \
23702 case value_t::number_unsigned: \
23703 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
23704 \
23705 case value_t::number_float: \
23706 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
23707 \
23708 case value_t::binary: \
23709 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
23710 \
23711 case value_t::discarded: \
23712 default: \
23713 return (unordered_result); \
23714 } \
23715 } \
23716 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
23717 { \
23718 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
23719 } \
23720 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
23721 { \
23722 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
23723 } \
23724 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
23725 { \
23726 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
23727 } \
23728 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
23729 { \
23730 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
23731 } \
23732 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
23733 { \
23734 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23735 } \
23736 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
23737 { \
23738 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23739 } \
23740 else if(compares_unordered(lhs, rhs))\
23741 {\
23742 return (unordered_result);\
23743 }\
23744 \
23745 return (default_result);
23746
23748 // returns true if:
23749 // - any operand is NaN and the other operand is of number type
23750 // - any operand is discarded
23751 // in legacy mode, discarded values are considered ordered if
23752 // an operation is computed as an odd number of inverses of others
23753 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23754 {
23755 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23756 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23757 {
23758 return true;
23759 }
23760#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23761 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23762#else
23763 static_cast<void>(inverse);
23764 return lhs.is_discarded() || rhs.is_discarded();
23765#endif
23766 }
23767
23768 private:
23769 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23770 {
23771 return compares_unordered(*this, rhs, inverse);
23772 }
23773
23774 public:
23775#if JSON_HAS_THREE_WAY_COMPARISON
23778 bool operator==(const_reference rhs) const noexcept
23779 {
23780#ifdef __GNUC__
23781#pragma GCC diagnostic push
23782#pragma GCC diagnostic ignored "-Wfloat-equal"
23783#endif
23784 const_reference lhs = *this;
23785 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23786#ifdef __GNUC__
23787#pragma GCC diagnostic pop
23788#endif
23789 }
23790
23793 template<typename ScalarType>
23794 requires std::is_scalar_v<ScalarType>
23795 bool operator==(ScalarType rhs) const noexcept
23796 {
23797 return *this == basic_json(rhs);
23798 }
23799
23802 bool operator!=(const_reference rhs) const noexcept
23803 {
23804 if (compares_unordered(rhs, true))
23805 {
23806 return false;
23807 }
23808 return !operator==(rhs);
23809 }
23810
23813 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23814 {
23815 const_reference lhs = *this;
23816 // default_result is used if we cannot compare values. In that case,
23817 // we compare types.
23818 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23819 std::partial_ordering::equivalent,
23820 std::partial_ordering::unordered,
23821 lhs_type <=> rhs_type) // *NOPAD*
23822 }
23823
23826 template<typename ScalarType>
23827 requires std::is_scalar_v<ScalarType>
23828 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23829 {
23830 return *this <=> basic_json(rhs); // *NOPAD*
23831 }
23832
23833#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23834 // all operators that are computed as an odd number of inverses of others
23835 // need to be overloaded to emulate the legacy comparison behavior
23836
23840 bool operator<=(const_reference rhs) const noexcept
23841 {
23842 if (compares_unordered(rhs, true))
23843 {
23844 return false;
23845 }
23846 return !(rhs < *this);
23847 }
23848
23851 template<typename ScalarType>
23852 requires std::is_scalar_v<ScalarType>
23853 bool operator<=(ScalarType rhs) const noexcept
23854 {
23855 return *this <= basic_json(rhs);
23856 }
23857
23861 bool operator>=(const_reference rhs) const noexcept
23862 {
23863 if (compares_unordered(rhs, true))
23864 {
23865 return false;
23866 }
23867 return !(*this < rhs);
23868 }
23869
23872 template<typename ScalarType>
23873 requires std::is_scalar_v<ScalarType>
23874 bool operator>=(ScalarType rhs) const noexcept
23875 {
23876 return *this >= basic_json(rhs);
23877 }
23878#endif
23879#else
23882 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23883 {
23884#ifdef __GNUC__
23885#pragma GCC diagnostic push
23886#pragma GCC diagnostic ignored "-Wfloat-equal"
23887#endif
23888 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23889#ifdef __GNUC__
23890#pragma GCC diagnostic pop
23891#endif
23892 }
23893
23896 template<typename ScalarType, typename std::enable_if<
23897 std::is_scalar<ScalarType>::value, int>::type = 0>
23898 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23899 {
23900 return lhs == basic_json(rhs);
23901 }
23902
23905 template<typename ScalarType, typename std::enable_if<
23906 std::is_scalar<ScalarType>::value, int>::type = 0>
23907 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23908 {
23909 return basic_json(lhs) == rhs;
23910 }
23911
23914 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23915 {
23916 if (compares_unordered(lhs, rhs, true))
23917 {
23918 return false;
23919 }
23920 return !(lhs == rhs);
23921 }
23922
23925 template<typename ScalarType, typename std::enable_if<
23926 std::is_scalar<ScalarType>::value, int>::type = 0>
23927 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23928 {
23929 return lhs != basic_json(rhs);
23930 }
23931
23934 template<typename ScalarType, typename std::enable_if<
23935 std::is_scalar<ScalarType>::value, int>::type = 0>
23936 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23937 {
23938 return basic_json(lhs) != rhs;
23939 }
23940
23943 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23944 {
23945 // default_result is used if we cannot compare values. In that case,
23946 // we compare types. Note we have to call the operator explicitly,
23947 // because MSVC has problems otherwise.
23948 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23949 }
23950
23953 template<typename ScalarType, typename std::enable_if<
23954 std::is_scalar<ScalarType>::value, int>::type = 0>
23955 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23956 {
23957 return lhs < basic_json(rhs);
23958 }
23959
23962 template<typename ScalarType, typename std::enable_if<
23963 std::is_scalar<ScalarType>::value, int>::type = 0>
23964 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23965 {
23966 return basic_json(lhs) < rhs;
23967 }
23968
23971 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23972 {
23973 if (compares_unordered(lhs, rhs, true))
23974 {
23975 return false;
23976 }
23977 return !(rhs < lhs);
23978 }
23979
23982 template<typename ScalarType, typename std::enable_if<
23983 std::is_scalar<ScalarType>::value, int>::type = 0>
23984 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23985 {
23986 return lhs <= basic_json(rhs);
23987 }
23988
23991 template<typename ScalarType, typename std::enable_if<
23992 std::is_scalar<ScalarType>::value, int>::type = 0>
23993 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23994 {
23995 return basic_json(lhs) <= rhs;
23996 }
23997
24000 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
24001 {
24002 // double inverse
24003 if (compares_unordered(lhs, rhs))
24004 {
24005 return false;
24006 }
24007 return !(lhs <= rhs);
24008 }
24009
24012 template<typename ScalarType, typename std::enable_if<
24013 std::is_scalar<ScalarType>::value, int>::type = 0>
24014 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
24015 {
24016 return lhs > basic_json(rhs);
24017 }
24018
24021 template<typename ScalarType, typename std::enable_if<
24022 std::is_scalar<ScalarType>::value, int>::type = 0>
24023 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
24024 {
24025 return basic_json(lhs) > rhs;
24026 }
24027
24030 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
24031 {
24032 if (compares_unordered(lhs, rhs, true))
24033 {
24034 return false;
24035 }
24036 return !(lhs < rhs);
24037 }
24038
24041 template<typename ScalarType, typename std::enable_if<
24042 std::is_scalar<ScalarType>::value, int>::type = 0>
24043 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
24044 {
24045 return lhs >= basic_json(rhs);
24046 }
24047
24050 template<typename ScalarType, typename std::enable_if<
24051 std::is_scalar<ScalarType>::value, int>::type = 0>
24052 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
24053 {
24054 return basic_json(lhs) >= rhs;
24055 }
24056#endif
24057
24058#undef JSON_IMPLEMENT_OPERATOR
24059
24061
24063 // serialization //
24065
24068#ifndef JSON_NO_IO
24071 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24072 {
24073 // read width member and use it as the indentation parameter if nonzero
24074 const bool pretty_print = o.width() > 0;
24075 const auto indentation = pretty_print ? o.width() : 0;
24076
24077 // reset width to 0 for subsequent calls to this stream
24078 o.width(0);
24079
24080 // do the actual serialization
24081 serializer s(detail::output_adapter<char>(o), o.fill());
24082 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24083 return o;
24084 }
24085
24092 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24093 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24094 {
24095 return o << j;
24096 }
24097#endif // JSON_NO_IO
24099
24101 // deserialization //
24103
24106
24109 template<typename InputType>
24111 static basic_json parse(InputType&& i,
24112 parser_callback_t cb = nullptr,
24113 const bool allow_exceptions = true,
24114 const bool ignore_comments = false)
24115 {
24116 basic_json result;
24117 parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
24118 return result;
24119 }
24120
24123 template<typename IteratorType>
24125 static basic_json parse(IteratorType first,
24126 IteratorType last,
24127 parser_callback_t cb = nullptr,
24128 const bool allow_exceptions = true,
24129 const bool ignore_comments = false)
24130 {
24131 basic_json result;
24132 parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24133 return result;
24134 }
24135
24137 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24138 static basic_json parse(detail::span_input_adapter&& i,
24139 parser_callback_t cb = nullptr,
24140 const bool allow_exceptions = true,
24141 const bool ignore_comments = false)
24142 {
24143 basic_json result;
24144 parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24145 return result;
24146 }
24147
24150 template<typename InputType>
24151 static bool accept(InputType&& i,
24152 const bool ignore_comments = false)
24153 {
24154 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
24155 }
24156
24159 template<typename IteratorType>
24160 static bool accept(IteratorType first, IteratorType last,
24161 const bool ignore_comments = false)
24162 {
24163 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
24164 }
24165
24167 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24168 static bool accept(detail::span_input_adapter&& i,
24169 const bool ignore_comments = false)
24170 {
24171 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
24172 }
24173
24176 template <typename InputType, typename SAX>
24178 static bool sax_parse(InputType&& i, SAX* sax,
24180 const bool strict = true,
24181 const bool ignore_comments = false)
24182 {
24183 auto ia = detail::input_adapter(std::forward<InputType>(i));
24184 return format == input_format_t::json
24185 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24186 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24187 }
24188
24191 template<class IteratorType, class SAX>
24193 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24195 const bool strict = true,
24196 const bool ignore_comments = false)
24197 {
24198 auto ia = detail::input_adapter(std::move(first), std::move(last));
24199 return format == input_format_t::json
24200 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24201 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24202 }
24203
24209 template <typename SAX>
24210 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24212 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24214 const bool strict = true,
24215 const bool ignore_comments = false)
24216 {
24217 auto ia = i.get();
24218 return format == input_format_t::json
24219 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24220 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24221 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24222 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24223 }
24224#ifndef JSON_NO_IO
24231 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24232 friend std::istream& operator<<(basic_json& j, std::istream& i)
24233 {
24234 return operator>>(i, j);
24235 }
24236
24239 friend std::istream& operator>>(std::istream& i, basic_json& j)
24240 {
24241 parser(detail::input_adapter(i)).parse(false, j);
24242 return i;
24243 }
24244#endif // JSON_NO_IO
24246
24248 // convenience functions //
24250
24254 const char* type_name() const noexcept
24255 {
24256 switch (m_data.m_type)
24257 {
24258 case value_t::null:
24259 return "null";
24260 case value_t::object:
24261 return "object";
24262 case value_t::array:
24263 return "array";
24264 case value_t::string:
24265 return "string";
24266 case value_t::boolean:
24267 return "boolean";
24268 case value_t::binary:
24269 return "binary";
24270 case value_t::discarded:
24271 return "discarded";
24272 case value_t::number_integer:
24273 case value_t::number_unsigned:
24274 case value_t::number_float:
24275 default:
24276 return "number";
24277 }
24278 }
24279
24282 // member variables //
24284
24285 struct data
24286 {
24288 value_t m_type = value_t::null;
24289
24291 json_value m_value = {};
24292
24293 data(const value_t v)
24294 : m_type(v), m_value(v)
24295 {
24296 }
24297
24298 data(size_type cnt, const basic_json& val)
24299 : m_type(value_t::array)
24300 {
24301 m_value.array = create<array_t>(cnt, val);
24302 }
24303
24304 data() noexcept = default;
24305 data(data&&) noexcept = default;
24306 data(const data&) noexcept = delete;
24307 data& operator=(data&&) noexcept = delete;
24308 data& operator=(const data&) noexcept = delete;
24309
24310 ~data() noexcept
24311 {
24312 m_value.destroy(m_type);
24313 }
24314 };
24315
24317
24318#if JSON_DIAGNOSTICS
24320 basic_json* m_parent = nullptr;
24321#endif
24322
24323#if JSON_DIAGNOSTIC_POSITIONS
24325 std::size_t start_position = std::string::npos;
24327 std::size_t end_position = std::string::npos;
24328 public:
24329 constexpr std::size_t start_pos() const noexcept
24330 {
24331 return start_position;
24332 }
24333
24334 constexpr std::size_t end_pos() const noexcept
24335 {
24336 return end_position;
24337 }
24338#endif
24339
24341 // binary serialization/deserialization //
24343
24346
24347 public:
24350 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24351 {
24352 std::vector<std::uint8_t> result;
24353 to_cbor(j, result);
24354 return result;
24355 }
24356
24360 {
24361 binary_writer<std::uint8_t>(o).write_cbor(j);
24362 }
24363
24367 {
24368 binary_writer<char>(o).write_cbor(j);
24369 }
24370
24373 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24374 {
24375 std::vector<std::uint8_t> result;
24376 to_msgpack(j, result);
24377 return result;
24378 }
24379
24383 {
24384 binary_writer<std::uint8_t>(o).write_msgpack(j);
24385 }
24386
24390 {
24391 binary_writer<char>(o).write_msgpack(j);
24392 }
24393
24396 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24397 const bool use_size = false,
24398 const bool use_type = false)
24399 {
24400 std::vector<std::uint8_t> result;
24401 to_ubjson(j, result, use_size, use_type);
24402 return result;
24403 }
24404
24408 const bool use_size = false, const bool use_type = false)
24409 {
24410 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24411 }
24412
24416 const bool use_size = false, const bool use_type = false)
24417 {
24418 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24419 }
24420
24423 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24424 const bool use_size = false,
24425 const bool use_type = false,
24426 const bjdata_version_t version = bjdata_version_t::draft2)
24427 {
24428 std::vector<std::uint8_t> result;
24429 to_bjdata(j, result, use_size, use_type, version);
24430 return result;
24431 }
24432
24436 const bool use_size = false, const bool use_type = false,
24437 const bjdata_version_t version = bjdata_version_t::draft2)
24438 {
24439 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24440 }
24441
24445 const bool use_size = false, const bool use_type = false,
24446 const bjdata_version_t version = bjdata_version_t::draft2)
24447 {
24448 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24449 }
24450
24453 static std::vector<std::uint8_t> to_bson(const basic_json& j)
24454 {
24455 std::vector<std::uint8_t> result;
24456 to_bson(j, result);
24457 return result;
24458 }
24459
24463 {
24464 binary_writer<std::uint8_t>(o).write_bson(j);
24465 }
24466
24470 {
24471 binary_writer<char>(o).write_bson(j);
24472 }
24473
24476 template<typename InputType>
24478 static basic_json from_cbor(InputType&& i,
24479 const bool strict = true,
24480 const bool allow_exceptions = true,
24481 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24482 {
24483 basic_json result;
24484 auto ia = detail::input_adapter(std::forward<InputType>(i));
24485 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24486 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24487 return res ? result : basic_json(value_t::discarded);
24488 }
24489
24492 template<typename IteratorType>
24494 static basic_json from_cbor(IteratorType first, IteratorType last,
24495 const bool strict = true,
24496 const bool allow_exceptions = true,
24497 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24498 {
24499 basic_json result;
24500 auto ia = detail::input_adapter(std::move(first), std::move(last));
24501 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24502 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24503 return res ? result : basic_json(value_t::discarded);
24504 }
24505
24506 template<typename T>
24508 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24509 static basic_json from_cbor(const T* ptr, std::size_t len,
24510 const bool strict = true,
24511 const bool allow_exceptions = true,
24512 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24513 {
24514 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24515 }
24516
24518 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24519 static basic_json from_cbor(detail::span_input_adapter&& i,
24520 const bool strict = true,
24521 const bool allow_exceptions = true,
24522 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24523 {
24524 basic_json result;
24525 auto ia = i.get();
24526 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24527 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24528 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24529 return res ? result : basic_json(value_t::discarded);
24530 }
24531
24534 template<typename InputType>
24536 static basic_json from_msgpack(InputType&& i,
24537 const bool strict = true,
24538 const bool allow_exceptions = true)
24539 {
24540 basic_json result;
24541 auto ia = detail::input_adapter(std::forward<InputType>(i));
24542 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24543 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24544 return res ? result : basic_json(value_t::discarded);
24545 }
24546
24549 template<typename IteratorType>
24551 static basic_json from_msgpack(IteratorType first, IteratorType last,
24552 const bool strict = true,
24553 const bool allow_exceptions = true)
24554 {
24555 basic_json result;
24556 auto ia = detail::input_adapter(std::move(first), std::move(last));
24557 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24558 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24559 return res ? result : basic_json(value_t::discarded);
24560 }
24561
24562 template<typename T>
24564 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24565 static basic_json from_msgpack(const T* ptr, std::size_t len,
24566 const bool strict = true,
24567 const bool allow_exceptions = true)
24568 {
24569 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24570 }
24571
24573 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24574 static basic_json from_msgpack(detail::span_input_adapter&& i,
24575 const bool strict = true,
24576 const bool allow_exceptions = true)
24577 {
24578 basic_json result;
24579 auto ia = i.get();
24580 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24581 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24582 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24583 return res ? result : basic_json(value_t::discarded);
24584 }
24585
24588 template<typename InputType>
24590 static basic_json from_ubjson(InputType&& i,
24591 const bool strict = true,
24592 const bool allow_exceptions = true)
24593 {
24594 basic_json result;
24595 auto ia = detail::input_adapter(std::forward<InputType>(i));
24596 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24597 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24598 return res ? result : basic_json(value_t::discarded);
24599 }
24600
24603 template<typename IteratorType>
24605 static basic_json from_ubjson(IteratorType first, IteratorType last,
24606 const bool strict = true,
24607 const bool allow_exceptions = true)
24608 {
24609 basic_json result;
24610 auto ia = detail::input_adapter(std::move(first), std::move(last));
24611 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24612 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24613 return res ? result : basic_json(value_t::discarded);
24614 }
24615
24616 template<typename T>
24618 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24619 static basic_json from_ubjson(const T* ptr, std::size_t len,
24620 const bool strict = true,
24621 const bool allow_exceptions = true)
24622 {
24623 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24624 }
24625
24627 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24628 static basic_json from_ubjson(detail::span_input_adapter&& i,
24629 const bool strict = true,
24630 const bool allow_exceptions = true)
24631 {
24632 basic_json result;
24633 auto ia = i.get();
24634 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24635 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24636 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24637 return res ? result : basic_json(value_t::discarded);
24638 }
24639
24642 template<typename InputType>
24644 static basic_json from_bjdata(InputType&& i,
24645 const bool strict = true,
24646 const bool allow_exceptions = true)
24647 {
24648 basic_json result;
24649 auto ia = detail::input_adapter(std::forward<InputType>(i));
24650 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24651 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24652 return res ? result : basic_json(value_t::discarded);
24653 }
24654
24657 template<typename IteratorType>
24659 static basic_json from_bjdata(IteratorType first, IteratorType last,
24660 const bool strict = true,
24661 const bool allow_exceptions = true)
24662 {
24663 basic_json result;
24664 auto ia = detail::input_adapter(std::move(first), std::move(last));
24665 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24666 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24667 return res ? result : basic_json(value_t::discarded);
24668 }
24669
24672 template<typename InputType>
24674 static basic_json from_bson(InputType&& i,
24675 const bool strict = true,
24676 const bool allow_exceptions = true)
24677 {
24678 basic_json result;
24679 auto ia = detail::input_adapter(std::forward<InputType>(i));
24680 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24681 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24682 return res ? result : basic_json(value_t::discarded);
24683 }
24684
24687 template<typename IteratorType>
24689 static basic_json from_bson(IteratorType first, IteratorType last,
24690 const bool strict = true,
24691 const bool allow_exceptions = true)
24692 {
24693 basic_json result;
24694 auto ia = detail::input_adapter(std::move(first), std::move(last));
24695 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24696 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24697 return res ? result : basic_json(value_t::discarded);
24698 }
24699
24700 template<typename T>
24702 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24703 static basic_json from_bson(const T* ptr, std::size_t len,
24704 const bool strict = true,
24705 const bool allow_exceptions = true)
24706 {
24707 return from_bson(ptr, ptr + len, strict, allow_exceptions);
24708 }
24709
24711 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24712 static basic_json from_bson(detail::span_input_adapter&& i,
24713 const bool strict = true,
24714 const bool allow_exceptions = true)
24715 {
24716 basic_json result;
24717 auto ia = i.get();
24718 detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24719 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24720 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24721 return res ? result : basic_json(value_t::discarded);
24722 }
24723
24724
24726 // JSON Pointer support //
24728
24731
24735 {
24736 return ptr.get_unchecked(this);
24737 }
24738
24739 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24740 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24741 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24742 {
24743 return ptr.get_unchecked(this);
24744 }
24745
24749 {
24750 return ptr.get_unchecked(this);
24751 }
24752
24753 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24754 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24755 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24756 {
24757 return ptr.get_unchecked(this);
24758 }
24759
24763 {
24764 return ptr.get_checked(this);
24765 }
24766
24767 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24768 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24769 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24770 {
24771 return ptr.get_checked(this);
24772 }
24773
24777 {
24778 return ptr.get_checked(this);
24779 }
24780
24781 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24782 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24783 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24784 {
24785 return ptr.get_checked(this);
24786 }
24787
24791 {
24792 basic_json result(value_t::object);
24793 json_pointer::flatten("", *this, result);
24794 return result;
24795 }
24796
24800 {
24801 return json_pointer::unflatten(*this);
24802 }
24803
24805
24807 // JSON Patch functions //
24809
24812
24815 void patch_inplace(const basic_json& json_patch)
24816 {
24817 basic_json& result = *this;
24818 // the valid JSON Patch operations
24819 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24820
24821 const auto get_op = [](const string_t& op)
24822 {
24823 if (op == "add")
24824 {
24825 return patch_operations::add;
24826 }
24827 if (op == "remove")
24828 {
24829 return patch_operations::remove;
24830 }
24831 if (op == "replace")
24832 {
24833 return patch_operations::replace;
24834 }
24835 if (op == "move")
24836 {
24837 return patch_operations::move;
24838 }
24839 if (op == "copy")
24840 {
24841 return patch_operations::copy;
24842 }
24843 if (op == "test")
24844 {
24845 return patch_operations::test;
24846 }
24847
24848 return patch_operations::invalid;
24849 };
24850
24851 // wrapper for "add" operation; add value at ptr
24852 const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24853 {
24854 // adding to the root of the target document means replacing it
24855 if (ptr.empty())
24856 {
24857 result = val;
24858 return;
24859 }
24860
24861 // make sure the top element of the pointer exists
24862 json_pointer const top_pointer = ptr.top();
24863 if (top_pointer != ptr)
24864 {
24865 result.at(top_pointer);
24866 }
24867
24868 // get reference to the parent of the JSON pointer ptr
24869 const auto last_path = ptr.back();
24870 ptr.pop_back();
24871 // parent must exist when performing patch add per RFC6902 specs
24872 basic_json& parent = result.at(ptr);
24873
24874 switch (parent.m_data.m_type)
24875 {
24876 case value_t::null:
24877 case value_t::object:
24878 {
24879 // use operator[] to add value
24880 parent[last_path] = val;
24881 break;
24882 }
24883
24884 case value_t::array:
24885 {
24886 if (last_path == "-")
24887 {
24888 // special case: append to back
24889 parent.push_back(val);
24890 }
24891 else
24892 {
24893 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24894 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24895 {
24896 // avoid undefined behavior
24897 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24898 }
24899
24900 // default case: insert add offset
24901 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24902 }
24903 break;
24904 }
24905
24906 // if there exists a parent, it cannot be primitive
24907 case value_t::string: // LCOV_EXCL_LINE
24908 case value_t::boolean: // LCOV_EXCL_LINE
24909 case value_t::number_integer: // LCOV_EXCL_LINE
24910 case value_t::number_unsigned: // LCOV_EXCL_LINE
24911 case value_t::number_float: // LCOV_EXCL_LINE
24912 case value_t::binary: // LCOV_EXCL_LINE
24913 case value_t::discarded: // LCOV_EXCL_LINE
24914 default: // LCOV_EXCL_LINE
24915 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24916 }
24917 };
24918
24919 // wrapper for "remove" operation; remove value at ptr
24920 const auto operation_remove = [this, & result](json_pointer & ptr)
24921 {
24922 // get reference to the parent of the JSON pointer ptr
24923 const auto last_path = ptr.back();
24924 ptr.pop_back();
24925 basic_json& parent = result.at(ptr);
24926
24927 // remove child
24928 if (parent.is_object())
24929 {
24930 // perform range check
24931 auto it = parent.find(last_path);
24932 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24933 {
24934 parent.erase(it);
24935 }
24936 else
24937 {
24938 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24939 }
24940 }
24941 else if (parent.is_array())
24942 {
24943 // note erase performs range check
24944 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24945 }
24946 };
24947
24948 // type check: top level value must be an array
24949 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24950 {
24951 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24952 }
24953
24954 // iterate and apply the operations
24955 for (const auto& val : json_patch)
24956 {
24957 // wrapper to get a value for an operation
24958 const auto get_value = [&val](const string_t& op,
24959 const string_t& member,
24960 bool string_type) -> basic_json &
24961 {
24962 // find value
24963 auto it = val.m_data.m_value.object->find(member);
24964
24965 // context-sensitive error message
24966 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24967
24968 // check if the desired value is present
24969 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24970 {
24971 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24972 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24973 }
24974
24975 // check if the result is of type string
24976 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24977 {
24978 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24979 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24980 }
24981
24982 // no error: return value
24983 return it->second;
24984 };
24985
24986 // type check: every element of the array must be an object
24987 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24988 {
24989 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24990 }
24991
24992 // collect mandatory members
24993 const auto op = get_value("op", "op", true).template get<string_t>();
24994 const auto path = get_value(op, "path", true).template get<string_t>();
24995 json_pointer ptr(path);
24996
24997 switch (get_op(op))
24998 {
24999 case patch_operations::add:
25000 {
25001 operation_add(ptr, get_value("add", "value", false));
25002 break;
25003 }
25004
25005 case patch_operations::remove:
25006 {
25007 operation_remove(ptr);
25008 break;
25009 }
25010
25011 case patch_operations::replace:
25012 {
25013 // the "path" location must exist - use at()
25014 result.at(ptr) = get_value("replace", "value", false);
25015 break;
25016 }
25017
25018 case patch_operations::move:
25019 {
25020 const auto from_path = get_value("move", "from", true).template get<string_t>();
25021 json_pointer from_ptr(from_path);
25022
25023 // the "from" location must exist - use at()
25024 basic_json const v = result.at(from_ptr);
25025
25026 // The move operation is functionally identical to a
25027 // "remove" operation on the "from" location, followed
25028 // immediately by an "add" operation at the target
25029 // location with the value that was just removed.
25030 operation_remove(from_ptr);
25031 operation_add(ptr, v);
25032 break;
25033 }
25034
25035 case patch_operations::copy:
25036 {
25037 const auto from_path = get_value("copy", "from", true).template get<string_t>();
25038 const json_pointer from_ptr(from_path);
25039
25040 // the "from" location must exist - use at()
25041 basic_json const v = result.at(from_ptr);
25042
25043 // The copy is functionally identical to an "add"
25044 // operation at the target location using the value
25045 // specified in the "from" member.
25046 operation_add(ptr, v);
25047 break;
25048 }
25049
25050 case patch_operations::test:
25051 {
25052 bool success = false;
25053 JSON_TRY
25054 {
25055 // check if "value" matches the one at "path"
25056 // the "path" location must exist - use at()
25057 success = (result.at(ptr) == get_value("test", "value", false));
25058 }
25060 {
25061 // ignore out of range errors: success remains false
25062 }
25063
25064 // throw an exception if the test fails
25065 if (JSON_HEDLEY_UNLIKELY(!success))
25066 {
25067 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25068 }
25069
25070 break;
25071 }
25072
25073 case patch_operations::invalid:
25074 default:
25075 {
25076 // op must be "add", "remove", "replace", "move", "copy", or
25077 // "test"
25078 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25079 }
25080 }
25081 }
25082 }
25083
25086 basic_json patch(const basic_json& json_patch) const
25087 {
25088 basic_json result = *this;
25089 result.patch_inplace(json_patch);
25090 return result;
25091 }
25092
25096 static basic_json diff(const basic_json& source, const basic_json& target,
25097 const string_t& path = "")
25098 {
25099 // the patch
25100 basic_json result(value_t::array);
25101
25102 // if the values are the same, return an empty patch
25103 if (source == target)
25104 {
25105 return result;
25106 }
25107
25108 if (source.type() != target.type())
25109 {
25110 // different types: replace value
25111 result.push_back(
25112 {
25113 {"op", "replace"}, {"path", path}, {"value", target}
25114 });
25115 return result;
25116 }
25117
25118 switch (source.type())
25119 {
25120 case value_t::array:
25121 {
25122 // first pass: traverse common elements
25123 std::size_t i = 0;
25124 while (i < source.size() && i < target.size())
25125 {
25126 // recursive call to compare array values at index i
25127 auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25128 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25129 ++i;
25130 }
25131
25132 // We now reached the end of at least one array
25133 // in a second pass, traverse the remaining elements
25134
25135 // remove my remaining elements
25136 const auto end_index = static_cast<difference_type>(result.size());
25137 while (i < source.size())
25138 {
25139 // add operations in reverse order to avoid invalid
25140 // indices
25141 result.insert(result.begin() + end_index, object(
25142 {
25143 {"op", "remove"},
25144 {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25145 }));
25146 ++i;
25147 }
25148
25149 // add other remaining elements
25150 while (i < target.size())
25151 {
25152 result.push_back(
25153 {
25154 {"op", "add"},
25155 {"path", detail::concat<string_t>(path, "/-")},
25156 {"value", target[i]}
25157 });
25158 ++i;
25159 }
25160
25161 break;
25162 }
25163
25164 case value_t::object:
25165 {
25166 // first pass: traverse this object's elements
25167 for (auto it = source.cbegin(); it != source.cend(); ++it)
25168 {
25169 // escape the key name to be used in a JSON patch
25170 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25171
25172 if (target.find(it.key()) != target.end())
25173 {
25174 // recursive call to compare object values at key it
25175 auto temp_diff = diff(it.value(), target[it.key()], path_key);
25176 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25177 }
25178 else
25179 {
25180 // found a key that is not in o -> remove it
25181 result.push_back(object(
25182 {
25183 {"op", "remove"}, {"path", path_key}
25184 }));
25185 }
25186 }
25187
25188 // second pass: traverse other object's elements
25189 for (auto it = target.cbegin(); it != target.cend(); ++it)
25190 {
25191 if (source.find(it.key()) == source.end())
25192 {
25193 // found a key that is not in this -> add it
25194 const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25195 result.push_back(
25196 {
25197 {"op", "add"}, {"path", path_key},
25198 {"value", it.value()}
25199 });
25200 }
25201 }
25202
25203 break;
25204 }
25205
25206 case value_t::null:
25207 case value_t::string:
25208 case value_t::boolean:
25209 case value_t::number_integer:
25210 case value_t::number_unsigned:
25211 case value_t::number_float:
25212 case value_t::binary:
25213 case value_t::discarded:
25214 default:
25215 {
25216 // both primitive types: replace value
25217 result.push_back(
25218 {
25219 {"op", "replace"}, {"path", path}, {"value", target}
25220 });
25221 break;
25222 }
25223 }
25224
25225 return result;
25226 }
25227
25228
25230 // JSON Merge Patch functions //
25232
25235
25238 void merge_patch(const basic_json& apply_patch)
25239 {
25240 if (apply_patch.is_object())
25241 {
25242 if (!is_object())
25243 {
25244 *this = object();
25245 }
25246 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25247 {
25248 if (it.value().is_null())
25249 {
25250 erase(it.key());
25251 }
25252 else
25253 {
25254 operator[](it.key()).merge_patch(it.value());
25255 }
25256 }
25257 }
25258 else
25259 {
25260 *this = apply_patch;
25261 }
25262 }
25263
25265};
25266
25271{
25272 return j.dump();
25273}
25274
25275inline namespace literals
25276{
25277inline namespace json_literals
25278{
25279
25283#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25284 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25285#else
25286 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25287#endif
25288{
25289 return nlohmann::json::parse(s, s + n);
25290}
25291
25295#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25296 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25297#else
25298 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25299#endif
25300{
25301 return nlohmann::json::json_pointer(std::string(s, n));
25302}
25303
25304} // namespace json_literals
25305} // namespace literals
25307
25309// nonmember support //
25311
25312namespace std // NOLINT(cert-dcl58-cpp)
25313{
25314
25318struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25319{
25320 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25321 {
25322 return nlohmann::detail::hash(j);
25323 }
25324};
25325
25326// specialization for std::less<value_t>
25327template<>
25328struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25329{
25334 bool operator()(::nlohmann::detail::value_t lhs,
25335 ::nlohmann::detail::value_t rhs) const noexcept
25336 {
25337#if JSON_HAS_THREE_WAY_COMPARISON
25338 return std::is_lt(lhs <=> rhs); // *NOPAD*
25339#else
25340 return ::nlohmann::detail::operator<(lhs, rhs);
25341#endif
25342 }
25343};
25344
25345// C++20 prohibit function specialization in the std namespace.
25346#ifndef JSON_HAS_CPP_20
25347
25351inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25352 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25353 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25354{
25355 j1.swap(j2);
25356}
25357
25358#endif
25359
25360} // namespace std
25361
25362#if JSON_USE_GLOBAL_UDLS
25363 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25364 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25365 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25366 #else
25367 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25368 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25369 #endif
25370#endif
25371
25372// #include <nlohmann/detail/macro_unscope.hpp>
25373// __ _____ _____ _____
25374// __| | __| | | | JSON for Modern C++
25375// | | |__ | | | | | | version 3.12.0
25376// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25377//
25378// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25379// SPDX-License-Identifier: MIT
25380
25381
25382
25383// restore clang diagnostic settings
25384#if defined(__clang__)
25385 #pragma clang diagnostic pop
25386#endif
25387
25388// clean up
25389#undef JSON_ASSERT
25390#undef JSON_INTERNAL_CATCH
25391#undef JSON_THROW
25392#undef JSON_PRIVATE_UNLESS_TESTED
25393#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25394#undef NLOHMANN_BASIC_JSON_TPL
25395#undef JSON_EXPLICIT
25396#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25397#undef JSON_INLINE_VARIABLE
25398#undef JSON_NO_UNIQUE_ADDRESS
25399#undef JSON_DISABLE_ENUM_SERIALIZATION
25400#undef JSON_USE_GLOBAL_UDLS
25401
25402#ifndef JSON_TEST_KEEP_MACROS
25403 #undef JSON_CATCH
25404 #undef JSON_TRY
25405 #undef JSON_HAS_CPP_11
25406 #undef JSON_HAS_CPP_14
25407 #undef JSON_HAS_CPP_17
25408 #undef JSON_HAS_CPP_20
25409 #undef JSON_HAS_CPP_23
25410 #undef JSON_HAS_FILESYSTEM
25411 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25412 #undef JSON_HAS_THREE_WAY_COMPARISON
25413 #undef JSON_HAS_RANGES
25414 #undef JSON_HAS_STATIC_RTTI
25415 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25416#endif
25417
25418// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25419// __ _____ _____ _____
25420// __| | __| | | | JSON for Modern C++
25421// | | |__ | | | | | | version 3.12.0
25422// |_____|_____|_____|_|___| https://github.com/nlohmann/json
25423//
25424// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25425// SPDX-License-Identifier: MIT
25426
25427
25428
25429#undef JSON_HEDLEY_ALWAYS_INLINE
25430#undef JSON_HEDLEY_ARM_VERSION
25431#undef JSON_HEDLEY_ARM_VERSION_CHECK
25432#undef JSON_HEDLEY_ARRAY_PARAM
25433#undef JSON_HEDLEY_ASSUME
25434#undef JSON_HEDLEY_BEGIN_C_DECLS
25435#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25436#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25437#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25438#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25439#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25440#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25441#undef JSON_HEDLEY_CLANG_HAS_WARNING
25442#undef JSON_HEDLEY_COMPCERT_VERSION
25443#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25444#undef JSON_HEDLEY_CONCAT
25445#undef JSON_HEDLEY_CONCAT3
25446#undef JSON_HEDLEY_CONCAT3_EX
25447#undef JSON_HEDLEY_CONCAT_EX
25448#undef JSON_HEDLEY_CONST
25449#undef JSON_HEDLEY_CONSTEXPR
25450#undef JSON_HEDLEY_CONST_CAST
25451#undef JSON_HEDLEY_CPP_CAST
25452#undef JSON_HEDLEY_CRAY_VERSION
25453#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25454#undef JSON_HEDLEY_C_DECL
25455#undef JSON_HEDLEY_DEPRECATED
25456#undef JSON_HEDLEY_DEPRECATED_FOR
25457#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25458#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25459#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25460#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25461#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25462#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25463#undef JSON_HEDLEY_DIAGNOSTIC_POP
25464#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25465#undef JSON_HEDLEY_DMC_VERSION
25466#undef JSON_HEDLEY_DMC_VERSION_CHECK
25467#undef JSON_HEDLEY_EMPTY_BASES
25468#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25469#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25470#undef JSON_HEDLEY_END_C_DECLS
25471#undef JSON_HEDLEY_FLAGS
25472#undef JSON_HEDLEY_FLAGS_CAST
25473#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25474#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25475#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25476#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25477#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25478#undef JSON_HEDLEY_GCC_HAS_FEATURE
25479#undef JSON_HEDLEY_GCC_HAS_WARNING
25480#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25481#undef JSON_HEDLEY_GCC_VERSION
25482#undef JSON_HEDLEY_GCC_VERSION_CHECK
25483#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25484#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25485#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25486#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25487#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25488#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25489#undef JSON_HEDLEY_GNUC_HAS_WARNING
25490#undef JSON_HEDLEY_GNUC_VERSION
25491#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25492#undef JSON_HEDLEY_HAS_ATTRIBUTE
25493#undef JSON_HEDLEY_HAS_BUILTIN
25494#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25495#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25496#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25497#undef JSON_HEDLEY_HAS_EXTENSION
25498#undef JSON_HEDLEY_HAS_FEATURE
25499#undef JSON_HEDLEY_HAS_WARNING
25500#undef JSON_HEDLEY_IAR_VERSION
25501#undef JSON_HEDLEY_IAR_VERSION_CHECK
25502#undef JSON_HEDLEY_IBM_VERSION
25503#undef JSON_HEDLEY_IBM_VERSION_CHECK
25504#undef JSON_HEDLEY_IMPORT
25505#undef JSON_HEDLEY_INLINE
25506#undef JSON_HEDLEY_INTEL_CL_VERSION
25507#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25508#undef JSON_HEDLEY_INTEL_VERSION
25509#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25510#undef JSON_HEDLEY_IS_CONSTANT
25511#undef JSON_HEDLEY_IS_CONSTEXPR_
25512#undef JSON_HEDLEY_LIKELY
25513#undef JSON_HEDLEY_MALLOC
25514#undef JSON_HEDLEY_MCST_LCC_VERSION
25515#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25516#undef JSON_HEDLEY_MESSAGE
25517#undef JSON_HEDLEY_MSVC_VERSION
25518#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25519#undef JSON_HEDLEY_NEVER_INLINE
25520#undef JSON_HEDLEY_NON_NULL
25521#undef JSON_HEDLEY_NO_ESCAPE
25522#undef JSON_HEDLEY_NO_RETURN
25523#undef JSON_HEDLEY_NO_THROW
25524#undef JSON_HEDLEY_NULL
25525#undef JSON_HEDLEY_PELLES_VERSION
25526#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25527#undef JSON_HEDLEY_PGI_VERSION
25528#undef JSON_HEDLEY_PGI_VERSION_CHECK
25529#undef JSON_HEDLEY_PREDICT
25530#undef JSON_HEDLEY_PRINTF_FORMAT
25531#undef JSON_HEDLEY_PRIVATE
25532#undef JSON_HEDLEY_PUBLIC
25533#undef JSON_HEDLEY_PURE
25534#undef JSON_HEDLEY_REINTERPRET_CAST
25535#undef JSON_HEDLEY_REQUIRE
25536#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25537#undef JSON_HEDLEY_REQUIRE_MSG
25538#undef JSON_HEDLEY_RESTRICT
25539#undef JSON_HEDLEY_RETURNS_NON_NULL
25540#undef JSON_HEDLEY_SENTINEL
25541#undef JSON_HEDLEY_STATIC_ASSERT
25542#undef JSON_HEDLEY_STATIC_CAST
25543#undef JSON_HEDLEY_STRINGIFY
25544#undef JSON_HEDLEY_STRINGIFY_EX
25545#undef JSON_HEDLEY_SUNPRO_VERSION
25546#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25547#undef JSON_HEDLEY_TINYC_VERSION
25548#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25549#undef JSON_HEDLEY_TI_ARMCL_VERSION
25550#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25551#undef JSON_HEDLEY_TI_CL2000_VERSION
25552#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25553#undef JSON_HEDLEY_TI_CL430_VERSION
25554#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25555#undef JSON_HEDLEY_TI_CL6X_VERSION
25556#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25557#undef JSON_HEDLEY_TI_CL7X_VERSION
25558#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25559#undef JSON_HEDLEY_TI_CLPRU_VERSION
25560#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25561#undef JSON_HEDLEY_TI_VERSION
25562#undef JSON_HEDLEY_TI_VERSION_CHECK
25563#undef JSON_HEDLEY_UNAVAILABLE
25564#undef JSON_HEDLEY_UNLIKELY
25565#undef JSON_HEDLEY_UNPREDICTABLE
25566#undef JSON_HEDLEY_UNREACHABLE
25567#undef JSON_HEDLEY_UNREACHABLE_RETURN
25568#undef JSON_HEDLEY_VERSION
25569#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25570#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25571#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25572#undef JSON_HEDLEY_VERSION_ENCODE
25573#undef JSON_HEDLEY_WARNING
25574#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25575#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25576#undef JSON_HEDLEY_FALL_THROUGH
25577
25578
25579
25580#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:20166
constexpr bool is_string() const noexcept
Definition json.hpp:21464
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:22699
detail::cbor_tag_handler_t cbor_tag_handler_t
Definition json.hpp:20239
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:22265
size_type size() const noexcept
Definition json.hpp:23040
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:24494
auto get() const noexcept(noexcept(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))) -> decltype(std::declval< const basic_json_t & >().template get_impl< ValueType >(detail::priority_tag< 4 > {}))
Definition json.hpp:21837
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22897
reference back()
access the last element
Definition json.hpp:22503
basic_json value_type
Definition json.hpp:20276
basic_json(CompatibleType &&val) noexcept(noexcept(//NOLINT(bugprone-forwarding-reference-overload, bugprone-exception-escape) JSONSerializer< U >::to_json(std::declval< basic_json_t & >(), std::forward< CompatibleType >(val))))
create a JSON value from compatible types
Definition json.hpp:20904
detail::parse_error parse_error
Definition json.hpp:20258
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22913
detail::input_format_t input_format_t
Definition json.hpp:20245
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:25086
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
Definition json.hpp:24254
const_reference front() const
access the first element
Definition json.hpp:22496
constexpr bool is_array() const noexcept
Definition json.hpp:21457
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
Definition json.hpp:23558
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22446
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22816
iter_impl< const basic_json > const_iterator
Definition json.hpp:20299
constexpr bool is_number_integer() const noexcept
Definition json.hpp:21429
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
Definition json.hpp:20303
data(size_type cnt, const basic_json &val)
Definition json.hpp:24298
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24689
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24734
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
Definition json.hpp:20294
std::size_t size_type
Definition json.hpp:20286
detail::type_error type_error
Definition json.hpp:20260
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:21401
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:22289
detail::error_handler_t error_handler_t
Definition json.hpp:20237
const value_type & const_reference
Definition json.hpp:20281
detail::invalid_iterator invalid_iterator
Definition json.hpp:20259
void swap(binary_t &other)
exchanges the values
Definition json.hpp:23635
ReferenceType get_ref()
Definition json.hpp:21927
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:23079
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23504
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21938
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:21478
JSON_PRIVATE_UNLESS_TESTED const_reference rhs
Definition json.hpp:23753
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:23295
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:23183
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:22234
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22985
const_reference back() const
access the last element
Definition json.hpp:22512
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:22594
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:23240
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:23575
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:24590
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:21046
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:23407
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bson(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BSON format
Definition json.hpp:24674
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:20309
nlohmann::byte_container_with_subtype< std::vector< std::uint8_t > > binary_t
Definition json.hpp:20434
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:22097
iterator end() noexcept
Definition json.hpp:22888
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:21436
void update(const_iterator first, const_iterator last, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:23511
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:24453
detail::exception exception
Definition json.hpp:20257
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22920
data m_data
Definition json.hpp:24316
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:23279
detail::parser_callback_t< basic_json > parser_callback_t
Definition json.hpp:20871
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:21087
ValueType & get_to(ValueType &v) const
Definition json.hpp:21904
static void to_msgpack(const basic_json &j, detail::output_adapter< char > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24389
iterator begin() noexcept
Definition json.hpp:22863
detail::parse_event_t parse_event_t
Definition json.hpp:20867
JSON_PRIVATE_UNLESS_TESTED const_reference bool inverse
Definition json.hpp:23753
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:22344
const_iterator cend() const noexcept
Definition json.hpp:22904
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24644
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24776
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:21057
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20892
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_cbor(InputType &&i, const bool strict=true, const bool allow_exceptions=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
create a JSON value from an input in CBOR format
Definition json.hpp:24478
basic_json flatten() const
return flattened JSON value
Definition json.hpp:24790
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_ubjson(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in UBJSON format
Definition json.hpp:24605
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:22710
std::vector< basic_json, std::allocator< basic_json > > array_t
Definition json.hpp:20410
nlohmann::ordered_map< std::string, basic_json, default_object_comparator_t, std::allocator< std::pair< const std::string, basic_json > > > object_t
Definition json.hpp:20402
const binary_t & get_binary() const
get a binary value
Definition json.hpp:22009
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:23427
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24815
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22397
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:24748
value_type & reference
Definition json.hpp:20279
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
Definition json.hpp:20243
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22833
static void to_cbor(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:24359
static void to_bson(const basic_json &j, detail::output_adapter< char > o)
create a BSON serialization of a given JSON value
Definition json.hpp:24469
iterator find(const typename object_t::key_type &key)
Definition json.hpp:22746
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(const typename binary_t::container_type &init)
explicitly create a binary array (without subtype)
Definition json.hpp:21035
static std::vector< std::uint8_t > to_bjdata(const basic_json &j, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24423
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:22135
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:20317
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:21094
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:22760
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:24350
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:22524
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:23380
double number_float_t
Definition json.hpp:20430
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22319
std::allocator< basic_json > allocator_type
Definition json.hpp:20289
typename std::allocator_traits< allocator_type >::pointer pointer
Definition json.hpp:20292
string_t dump(const int indent=-1, const char indent_char=' ', const bool ensure_ascii=false, const error_handler_t error_handler=error_handler_t::strict) const
serialization
Definition json.hpp:21365
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:25238
ValueType & get_to(ValueType &v) const noexcept(noexcept(JSONSerializer< ValueType >::from_json(std::declval< const basic_json_t & >(), v)))
get a value (explicit)
Definition json.hpp:21891
static void to_bjdata(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24435
reference operator[](T *key)
Definition json.hpp:22250
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:22031
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:22776
constexpr bool is_number_float() const noexcept
Definition json.hpp:21443
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22927
static std::vector< std::uint8_t > to_ubjson(const basic_json &j, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24396
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:24762
bool boolean_t
Definition json.hpp:20418
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json diff(const basic_json &source, const basic_json &target, const string_t &path="")
creates a diff as a JSON patch
Definition json.hpp:25096
detail::value_t value_t
Definition json.hpp:20231
std::less< std::string > default_object_comparator_t
Definition json.hpp:20397
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23271
const_iterator cbegin() const noexcept
Definition json.hpp:22879
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:22212
constexpr auto get_ptr() const noexcept -> decltype(std::declval< const basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21649
~basic_json() noexcept
destructor
Definition json.hpp:21347
detail::out_of_range out_of_range
Definition json.hpp:20261
const_reverse_iterator crend() const noexcept
Definition json.hpp:22948
basic_json(initializer_list_t init, bool type_deduction=true, value_t manual_type=value_t::array)
create a container (array or object) from an initializer list
Definition json.hpp:20976
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:23651
binary_t & get_binary()
get a binary value
Definition json.hpp:21997
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22872
constexpr bool is_number() const noexcept
Definition json.hpp:21422
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:23478
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(InputType &&i, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:24536
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21878
const_reference operator[](T *key) const
Definition json.hpp:22256
data(const value_t v)
Definition json.hpp:24293
reference operator[](size_type idx)
access specified array element
Definition json.hpp:22153
basic_json(const JsonRef &ref)
Definition json.hpp:21215
adl_serializer< T, SFINAE > json_serializer
Definition json.hpp:20235
basic_json & operator=(basic_json other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&std::is_nothrow_move_assignable< json_value >::value &&std::is_nothrow_move_assignable< json_base_class_t >::value)
copy assignment
Definition json.hpp:21318
static iteration_proxy< iterator > iterator_wrapper(reference ref) noexcept
Definition json.hpp:22960
static void to_ubjson(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24415
Array get_to(T(&v)[N]) const noexcept(noexcept(JSONSerializer< Array >::from_json(std::declval< const basic_json_t & >(), v)))
Definition json.hpp:21915
std::int64_t number_integer_t
Definition json.hpp:20422
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:21638
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:22115
constexpr bool is_binary() const noexcept
Definition json.hpp:21471
void swap(object_t &other)
exchanges the values
Definition json.hpp:23603
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:24799
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:23458
static void to_bjdata(const basic_json &j, detail::output_adapter< char > o, const bool use_size=false, const bool use_type=false, const bjdata_version_t version=bjdata_version_t::draft2)
create a BJData serialization of a given JSON value
Definition json.hpp:24444
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init, typename binary_t::subtype_type subtype)
explicitly create a binary array (with subtype)
Definition json.hpp:21068
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22978
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:23001
void swap(array_t &other)
exchanges the values
Definition json.hpp:23587
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:22717
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:23208
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22840
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:21387
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:23304
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:22420
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:21079
detail::bjdata_version_t bjdata_version_t
Definition json.hpp:20241
data() noexcept=default
std::string string_t
Definition json.hpp:20414
friend class ::nlohmann::detail::parser
Definition json.hpp:20176
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:23216
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:22370
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:22077
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_bjdata(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in BJData format
Definition json.hpp:24659
json_value m_value
Definition json.hpp:24291
const_reverse_iterator crbegin() const noexcept
Definition json.hpp:22941
json_sax< basic_json > json_sax_t
Definition json.hpp:20247
constexpr bool is_boolean() const noexcept
Definition json.hpp:21415
size_type count(const typename object_t::key_type &key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22806
reference front()
access the first element
Definition json.hpp:22489
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:21394
constexpr bool is_null() const noexcept
Definition json.hpp:21408
void clear() noexcept
clears the contents
Definition json.hpp:23122
static void to_ubjson(const basic_json &j, detail::output_adapter< std::uint8_t > o, const bool use_size=false, const bool use_type=false)
create a UBJSON serialization of a given JSON value
Definition json.hpp:24407
detail::other_error other_error
Definition json.hpp:20262
JSON_PRIVATE_UNLESS_TESTED const_reference bool static SAX bool sax_parse(InputType &&i, SAX *sax, input_format_t format=input_format_t::json, const bool strict=true, const bool ignore_comments=false)
Definition json.hpp:24178
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:21292
iter_impl< basic_json > iterator
Definition json.hpp:20297
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20884
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:22199
std::ptrdiff_t difference_type
Definition json.hpp:20284
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:23400
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22934
std::uint64_t number_unsigned_t
Definition json.hpp:20426
friend std::istream & operator>>(std::istream &i, basic_json &j)
Definition json.hpp:24239
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24373
void swap(string_t &other)
exchanges the values
Definition json.hpp:23619
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20918
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
Definition json.hpp:20301
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:22054
detail::actual_object_comparator_t< basic_json > object_comparator_t
Definition json.hpp:20438
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:21219
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:23248
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:23329
static void to_cbor(const basic_json &j, detail::output_adapter< char > o)
create a CBOR serialization of a given JSON value
Definition json.hpp:24366
constexpr bool is_object() const noexcept
Definition json.hpp:21450
static void to_msgpack(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a MessagePack serialization of a given JSON value
Definition json.hpp:24382
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json from_msgpack(IteratorType first, IteratorType last, const bool strict=true, const bool allow_exceptions=true)
create a JSON value from an input in MessagePack format
Definition json.hpp:24551
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:23361
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:21106
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22824
static void to_bson(const basic_json &j, detail::output_adapter< std::uint8_t > o)
create a BSON serialization of a given JSON value
Definition json.hpp:24462
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22792
::nlohmann::json_pointer< std::string > json_pointer
Definition json.hpp:20233
bool operator!=(const byte_container_with_subtype &rhs) const
Definition json.hpp:6273
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:6239
std::uint64_t subtype_type
Definition json.hpp:6236
bool operator==(const byte_container_with_subtype &rhs) const
Definition json.hpp:6267
BinaryType container_type
Definition json.hpp:6235
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6261
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:6249
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:6288
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:6254
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:6295
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:6244
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:6280
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:6302
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9885
binary_reader(const binary_reader &)=delete
binary_reader(binary_reader &&)=default
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9901
binary_reader & operator=(const binary_reader &)=delete
bool sax_parse(const input_format_t format, json_sax_t *sax_, const bool strict=true, const cbor_tag_handler_t tag_handler=cbor_tag_handler_t::error)
Definition json.hpp:9922
binary_reader & operator=(binary_reader &&)=default
void write_bson(const BasicJsonType &j)
Definition json.hpp:15859
static constexpr CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17599
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false, const bjdata_version_t bjdata_version=bjdata_version_t::draft2)
Definition json.hpp:16539
static CharType to_char_type(std::uint8_t x) noexcept
Definition json.hpp:17606
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:15850
static constexpr CharType to_char_type(InputCharType x) noexcept
Definition json.hpp:17628
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:16212
void write_cbor(const BasicJsonType &j)
Definition json.hpp:15888
general exception of the basic_json class
Definition json.hpp:4534
exception(int id_, const char *what_arg)
Definition json.hpp:4547
const int id
the id of the exception
Definition json.hpp:4543
static std::string diagnostics(std::nullptr_t)
Definition json.hpp:4554
static std::string name(const std::string &ename, int id_)
Definition json.hpp:4549
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4537
static std::string diagnostics(const BasicJsonType *leaf_element)
Definition json.hpp:4560
Definition json.hpp:6535
char char_type
Definition json.hpp:6537
file_input_adapter(const file_input_adapter &)=delete
file_input_adapter(std::FILE *f) noexcept
Definition json.hpp:6540
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6553
file_input_adapter(file_input_adapter &&) noexcept=default
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6560
Definition json.hpp:6580
input_stream_adapter & operator=(input_stream_adapter &&)=delete
input_stream_adapter(input_stream_adapter &&rhs) noexcept
Definition json.hpp:6603
~input_stream_adapter()
Definition json.hpp:6584
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6625
std::char_traits< char >::int_type get_character()
Definition json.hpp:6613
char char_type
Definition json.hpp:6582
input_stream_adapter(const input_stream_adapter &)=delete
input_stream_adapter & operator=(input_stream_adapter &)=delete
input_stream_adapter(std::istream &i)
Definition json.hpp:6594
exception indicating errors with iterators
Definition json.hpp:4703
static invalid_iterator create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4706
~iter_impl()=default
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:14241
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13795
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:14186
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13785
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:14128
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:14168
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:14232
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:14038
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:14341
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:14079
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13976
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:14195
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14303
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer >::type pointer
Definition json.hpp:13690
pointer operator->() const
dereference the iterator
Definition json.hpp:13934
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:14274
iter_impl(iter_impl &&) noexcept=default
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:14252
reference value() const
return the value of an iterator
Definition json.hpp:14357
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:14177
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:13987
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13890
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14263
typename std::conditional< std::is_const< BasicJsonType >::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference >::type reference
Definition json.hpp:13694
iter_impl()=default
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13770
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:14119
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:14027
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13760
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13851
Definition json.hpp:5495
iteration_proxy_value operator++(int) &
Definition json.hpp:5551
iteration_proxy_value(iteration_proxy_value const &)=default
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5560
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5566
std::ptrdiff_t difference_type
Definition json.hpp:5497
value_type & reference
Definition json.hpp:5500
iteration_proxy_value(IteratorType it, std::size_t array_index_=0) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_default_constructible< string_type >::value)
Definition json.hpp:5518
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5543
std::forward_iterator_tag iterator_category
Definition json.hpp:5501
iteration_proxy_value value_type
Definition json.hpp:5498
iteration_proxy_value(iteration_proxy_value &&) noexcept(std::is_nothrow_move_constructible< IteratorType >::value &&std::is_nothrow_move_constructible< string_type >::value)=default
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5608
value_type * pointer
Definition json.hpp:5499
const string_type & key() const
return key of the iterator
Definition json.hpp:5572
iteration_proxy_value & operator=(iteration_proxy_value const &)=default
typename std::remove_cv< typename std::remove_reference< decltype(std::declval< IteratorType >().key()) >::type >::type string_type
Definition json.hpp:5502
proxy class for the items() function
Definition json.hpp:5616
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5641
iteration_proxy(iteration_proxy const &)=default
iteration_proxy(iteration_proxy &&) noexcept=default
iteration_proxy_value< IteratorType > begin() const noexcept
return iterator begin (needed for range-based for)
Definition json.hpp:5635
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5625
iteration_proxy & operator=(iteration_proxy const &)=default
Definition json.hpp:6646
char_traits< char_type >::int_type get_character()
Definition json.hpp:6654
iterator_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6650
typename std::iterator_traits< IteratorType >::value_type char_type
Definition json.hpp:6648
std::size_t get_elements(T *dest, std::size_t count=1)
Definition json.hpp:6668
friend struct wide_string_input_helper
Definition json.hpp:6691
Definition json.hpp:15571
json_ref(json_ref &&) noexcept=default
json_ref(const value_type &value)
Definition json.hpp:15579
json_ref(value_type &&value)
Definition json.hpp:15575
value_type const & operator*() const
Definition json.hpp:15610
value_type const * operator->() const
Definition json.hpp:15615
json_ref(std::initializer_list< json_ref > init)
Definition json.hpp:15583
json_ref(Args &&... args)
Definition json.hpp:15590
value_type moved_or_copied() const
Definition json.hpp:15601
BasicJsonType value_type
Definition json.hpp:15573
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:14436
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:14448
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:14442
std::ptrdiff_t difference_type
Definition json.hpp:14422
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:14460
reference operator[](difference_type n) const
access to successor
Definition json.hpp:14484
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:14490
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:14478
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:14426
reference value() const
return the value of an iterator
Definition json.hpp:14497
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:14433
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:14454
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:14424
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:14472
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:14429
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:14466
Definition json.hpp:9600
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9603
bool end_object()
Definition json.hpp:9653
bool binary(binary_t &)
Definition json.hpp:9638
bool number_integer(number_integer_t)
Definition json.hpp:9618
bool start_array(std::size_t=detail::unknown_size())
Definition json.hpp:9658
bool boolean(bool)
Definition json.hpp:9613
bool null()
Definition json.hpp:9608
bool end_array()
Definition json.hpp:9663
bool number_unsigned(number_unsigned_t)
Definition json.hpp:9623
bool start_object(std::size_t=detail::unknown_size())
Definition json.hpp:9643
bool string(string_t &)
Definition json.hpp:9633
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9606
bool number_float(number_float_t, const string_t &)
Definition json.hpp:9628
bool parse_error(std::size_t, const std::string &, const detail::exception &)
Definition json.hpp:9668
bool key(string_t &)
Definition json.hpp:9648
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9602
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9604
typename BasicJsonType::string_t string_t
Definition json.hpp:9605
Definition json.hpp:9163
bool start_array(std::size_t len)
Definition json.hpp:9331
typename BasicJsonType::parser_callback_t parser_callback_t
Definition json.hpp:9170
bool null()
Definition json.hpp:9190
typename BasicJsonType::parse_event_t parse_event_t
Definition json.hpp:9171
json_sax_dom_callback_parser & operator=(json_sax_dom_callback_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:9202
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9410
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:9167
json_sax_dom_callback_parser & operator=(const json_sax_dom_callback_parser &)=delete
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:9172
bool end_object()
Definition json.hpp:9281
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:9208
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:9214
constexpr bool is_errored() const
Definition json.hpp:9422
json_sax_dom_callback_parser(BasicJsonType &r, parser_callback_t cb, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:9174
bool binary(binary_t &val)
Definition json.hpp:9226
typename BasicJsonType::string_t string_t
Definition json.hpp:9168
bool boolean(bool val)
Definition json.hpp:9196
bool key(string_t &val)
Definition json.hpp:9264
bool string(string_t &val)
Definition json.hpp:9220
json_sax_dom_callback_parser(json_sax_dom_callback_parser &&)=default
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:9166
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:9165
typename BasicJsonType::binary_t binary_t
Definition json.hpp:9169
bool end_array()
Definition json.hpp:9363
bool start_object(std::size_t len)
Definition json.hpp:9232
json_sax_dom_callback_parser(const json_sax_dom_callback_parser &)=delete
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:8857
bool number_float(number_float_t val, const string_t &)
Definition json.hpp:8906
bool number_unsigned(number_unsigned_t val)
Definition json.hpp:8900
json_sax_dom_parser(const json_sax_dom_parser &)=delete
json_sax_dom_parser & operator=(const json_sax_dom_parser &)=delete
bool binary(binary_t &val)
Definition json.hpp:8918
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8863
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true, lexer_t *lexer_=nullptr)
Definition json.hpp:8871
bool start_object(std::size_t len)
Definition json.hpp:8924
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8859
bool key(string_t &val)
Definition json.hpp:8947
bool end_object()
Definition json.hpp:8957
typename BasicJsonType::string_t string_t
Definition json.hpp:8862
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8860
bool parse_error(std::size_t, const std::string &, const Exception &ex)
Definition json.hpp:9015
lexer< BasicJsonType, InputAdapterType > lexer_t
Definition json.hpp:8864
bool boolean(bool val)
Definition json.hpp:8888
bool start_array(std::size_t len)
Definition json.hpp:8975
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8861
bool end_array()
Definition json.hpp:8996
json_sax_dom_parser(json_sax_dom_parser &&)=default
constexpr bool is_errored() const
Definition json.hpp:9027
bool null()
Definition json.hpp:8882
bool string(string_t &val)
Definition json.hpp:8912
json_sax_dom_parser & operator=(json_sax_dom_parser &&)=default
bool number_integer(number_integer_t val)
Definition json.hpp:8894
Definition json.hpp:7097
JSON_HEDLEY_RETURNS_NON_NULL static JSON_HEDLEY_CONST const char * token_type_name(const token_type t) noexcept
return name of values of type token_type (only used for errors)
Definition json.hpp:7124
token_type
token types for the parser
Definition json.hpp:7101
@ value_float
an floating point number – use get_number_float() for actual value
Definition json.hpp:7109
@ begin_array
the character for array begin [
Definition json.hpp:7110
@ value_string
a string – use get_string() for actual value
Definition json.hpp:7106
@ end_array
the character for array end ]
Definition json.hpp:7112
@ uninitialized
indicating the scanner is uninitialized
Definition json.hpp:7102
@ parse_error
indicating a parse error
Definition json.hpp:7116
@ value_integer
a signed integer – use get_number_integer() for actual value
Definition json.hpp:7108
@ value_separator
the value separator ,
Definition json.hpp:7115
@ end_object
the character for object end }
Definition json.hpp:7113
@ literal_true
the true literal
Definition json.hpp:7103
@ begin_object
the character for object begin {
Definition json.hpp:7111
@ value_unsigned
an unsigned integer – use get_number_unsigned() for actual value
Definition json.hpp:7107
@ literal_null
the null literal
Definition json.hpp:7105
@ end_of_input
indicating the end of the input buffer
Definition json.hpp:7117
@ name_separator
the name separator :
Definition json.hpp:7114
@ literal_or_value
a literal or the begin of a value (only for diagnostics)
Definition json.hpp:7118
@ literal_false
the false literal
Definition json.hpp:7104
lexical analysis
Definition json.hpp:7174
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8556
void skip_whitespace()
Definition json.hpp:8570
lexer(InputAdapterType &&adapter, bool ignore_comments_=false) noexcept
Definition json.hpp:7185
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8543
std::string get_token_string() const
Definition json.hpp:8518
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8477
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8510
token_type scan()
Definition json.hpp:8579
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8483
typename lexer_base< BasicJsonType >::token_type token_type
Definition json.hpp:7183
lexer(lexer &&)=default
~lexer()=default
lexer & operator=(lexer &&)=default
lexer(const lexer &)=delete
lexer & operator=(lexer &)=delete
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8495
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8489
exception indicating other library errors
Definition json.hpp:4755
static other_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4758
exception indicating access out of the defined range
Definition json.hpp:4738
static out_of_range create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4741
Definition json.hpp:15790
output_adapter(StringType &s)
Definition json.hpp:15801
output_adapter(std::basic_ostream< CharType > &s)
Definition json.hpp:15797
output_adapter(std::vector< CharType, AllocatorType > &vec)
Definition json.hpp:15793
output adapter for output streams
Definition json.hpp:15742
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15754
output_stream_adapter(std::basic_ostream< CharType > &s) noexcept
Definition json.hpp:15744
void write_character(CharType c) override
Definition json.hpp:15748
output adapter for basic_string
Definition json.hpp:15767
void write_character(CharType c) override
Definition json.hpp:15773
output_string_adapter(StringType &s) noexcept
Definition json.hpp:15769
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15779
output adapter for byte vectors
Definition json.hpp:15717
output_vector_adapter(std::vector< CharType, AllocatorType > &vec) noexcept
Definition json.hpp:15719
void write_characters(const CharType *s, std::size_t length) override
Definition json.hpp:15729
void write_character(CharType c) override
Definition json.hpp:15723
exception indicating a parse error
Definition json.hpp:4650
static parse_error create(int id_, const position_t &pos, const std::string &what_arg, BasicJsonContext context)
create a parse error exception
Definition json.hpp:4662
static parse_error create(int id_, std::size_t byte_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4670
const std::size_t byte
byte index of the parse error
Definition json.hpp:4687
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:13003
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:13063
parser(InputAdapterType &&adapter, parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
Definition json.hpp:12981
bool sax_parse(SAX *sax, const bool strict=true)
Definition json.hpp:13071
Definition json.hpp:13475
primitive_iterator_t & operator++() noexcept
Definition json.hpp:13537
primitive_iterator_t & operator-=(difference_type n) noexcept
Definition json.hpp:13569
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:13504
primitive_iterator_t & operator--() noexcept
Definition json.hpp:13550
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:13498
friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13520
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:13510
primitive_iterator_t operator++(int) &noexcept
Definition json.hpp:13543
primitive_iterator_t & operator+=(difference_type n) noexcept
Definition json.hpp:13563
friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13515
constexpr difference_type get_value() const noexcept
Definition json.hpp:13486
friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
Definition json.hpp:13532
primitive_iterator_t operator+(difference_type n) noexcept
Definition json.hpp:13525
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:13492
primitive_iterator_t operator--(int) &noexcept
Definition json.hpp:13556
std::array< char, 512 > string_buffer
string buffer
Definition json.hpp:19749
std::uint8_t state
Definition json.hpp:19167
std::size_t bytes_after_last_accept
Definition json.hpp:19171
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18840
JSON_PRIVATE_UNLESS_TESTED const bool ensure_ascii
Definition json.hpp:19165
std::size_t undumped_chars
Definition json.hpp:19172
const char thousands_sep
the locale's thousand separator character
Definition json.hpp:19744
const char decimal_point
the locale's decimal point character
Definition json.hpp:19746
serializer & operator=(const serializer &)=delete
~serializer()=default
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19757
string_t indent_string
the indentation string
Definition json.hpp:19754
const std::lconv * loc
the locale
Definition json.hpp:19742
serializer & operator=(serializer &&)=delete
std::array< char, 64 > number_buffer
a (hopefully) large enough character buffer
Definition json.hpp:19739
const char indent_char
the indentation character
Definition json.hpp:19752
std::size_t bytes
Definition json.hpp:19168
void dump(const BasicJsonType &val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent=0)
internal implementation of the serialization function
Definition json.hpp:18880
serializer(const serializer &)=delete
serializer(serializer &&)=delete
span_input_adapter(CharT b, std::size_t l)
Definition json.hpp:7016
span_input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:7023
contiguous_bytes_input_adapter && get()
Definition json.hpp:7026
exception indicating executing a member function with a wrong type
Definition json.hpp:4721
static type_error create(int id_, const std::string &what_arg, BasicJsonContext context)
Definition json.hpp:4724
Definition json.hpp:6825
std::size_t get_elements(T *, std::size_t=1)
Definition json.hpp:6851
std::char_traits< char >::int_type get_character() noexcept
Definition json.hpp:6832
wide_string_input_adapter(BaseInputAdapter base)
Definition json.hpp:6829
char char_type
Definition json.hpp:6827
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:14592
friend json_pointer operator/(const json_pointer &lhs, string_t token)
create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
Definition json.hpp:14687
typename string_t_helper< RefStringType >::type string_t
Definition json.hpp:14614
friend json_pointer operator/(const json_pointer &lhs, std::size_t array_idx)
create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
Definition json.hpp:14694
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:14618
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14753
void pop_back()
remove last reference token
Definition json.hpp:14715
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:14624
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:14672
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14746
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:14654
friend json_pointer operator/(const json_pointer &lhs, const json_pointer &rhs)
create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
Definition json.hpp:14679
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:14701
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:14664
friend class json_pointer
Definition json.hpp:14598
const string_t & back() const
return last reference token
Definition json.hpp:14727
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:14645
friend class basic_json
Definition json.hpp:14595
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14739
decltype( get< N >(std::declval< ::nlohmann::detail::iteration_proxy_value< IteratorType > >())) type
Definition json.hpp:5687
#define NLOHMANN_BASIC_JSON_TPL_DECLARATION
Definition json.hpp:2616
#define JSON_HEDLEY_CONST
Definition json.hpp:1829
#define JSON_HEDLEY_DIAGNOSTIC_PUSH
Definition json.hpp:1113
#define JSON_INLINE_VARIABLE
Definition json.hpp:2515
#define JSON_HEDLEY_WARN_UNUSED_RESULT
Definition json.hpp:1459
#define JSON_PRIVATE_UNLESS_TESTED
Definition json.hpp:2575
#define NLOHMANN_JSON_VERSION_PATCH
Definition json.hpp:70
#define JSON_HEDLEY_LIKELY(expr)
Definition json.hpp:1724
bool operator==(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15487
#define JSON_HEDLEY_NON_NULL(...)
Definition json.hpp:1617
#define JSON_INTERNAL_CATCH(exception)
Definition json.hpp:2542
NLOHMANN_BASIC_JSON_TPL_DECLARATION std::string to_string(const NLOHMANN_BASIC_JSON_TPL &j)
user-defined to_string function for JSON values
Definition json.hpp:25270
#define JSON_HEDLEY_RETURNS_NON_NULL
Definition json.hpp:2058
#define JSON_CATCH(exception)
Definition json.hpp:2541
#define JSON_ASSERT(x)
Definition json.hpp:2568
#define JSON_THROW(exception)
Definition json.hpp:2539
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
Definition json.hpp:81
#define NLOHMANN_JSON_VERSION_MAJOR
Definition json.hpp:68
bool operator<(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15537
#define NLOHMANN_BASIC_JSON_TPL
Definition json.hpp:2626
#define JSON_HEDLEY_UNLIKELY(expr)
Definition json.hpp:1725
#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
Definition json.hpp:12860
#define JSON_TRY
Definition json.hpp:2540
#define NLOHMANN_JSON_NAMESPACE_END
Definition json.hpp:155
#define JSON_NO_UNIQUE_ADDRESS
Definition json.hpp:2521
basic_json< nlohmann::ordered_map > ordered_json
specialization that maintains the insertion order of object keys
Definition json.hpp:3557
#define NLOHMANN_JSON_VERSION_MINOR
Definition json.hpp:69
#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)
Definition json.hpp:2910
bool operator!=(const json_pointer< RefStringTypeLhs > &lhs, const json_pointer< RefStringTypeRhs > &rhs) noexcept
Definition json.hpp:15512
#define NLOHMANN_JSON_NAMESPACE_BEGIN
Definition json.hpp:145
#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
Definition json.hpp:12857
#define JSON_HEDLEY_DIAGNOSTIC_POP
Definition json.hpp:1114
#define JSON_EXPLICIT
Definition json.hpp:2947
#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
Definition json.hpp:1407
#define JSON_HEDLEY_PURE
Definition json.hpp:1798
#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)
Definition json.hpp:23676
#define JSON_DIAGNOSTIC_POSITIONS
Definition json.hpp:77
implements the Grisu2 algorithm for binary to decimal floating-point conversion.
Definition json.hpp:17717
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:18164
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:18000
Target reinterpret_bits(const Source source)
Definition json.hpp:17720
boundaries compute_boundaries(FloatType value)
Definition json.hpp:17861
void grisu2_round(char *buf, int len, std::uint64_t dist, std::uint64_t delta, std::uint64_t rest, std::uint64_t ten_k)
Definition json.hpp:18218
constexpr int kAlpha
Definition json.hpp:17983
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:18500
constexpr int kGamma
Definition json.hpp:17984
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:18259
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:18600
JSON_HEDLEY_RETURNS_NON_NULL char * format_buffer(char *buf, int len, int decimal_exponent, int min_exp, int max_exp)
prettify v = buf * 10^decimal_exponent
Definition json.hpp:18652
Definition json.hpp:4313
constexpr bool is_transparent()
Definition json.hpp:4344
constexpr bool is_c_string()
Definition json.hpp:4316
Definition json.hpp:3264
detail namespace with internal helper functions
Definition json.hpp:260
make_integer_sequence< size_t, N > make_index_sequence
Definition json.hpp:3315
decltype(std::declval< StringType & >().append(std::declval< Arg && >())) string_can_append
Definition json.hpp:4419
std::integral_constant< bool,(std::is_signed< OfType >::value &&(sizeof(T)< sizeof(OfType)))||(same_sign< OfType, T >::value &&sizeof(OfType)==sizeof(T)) > never_out_of_range
Definition json.hpp:4226
input_format_t
the supported input formats
Definition json.hpp:6523
@ bson
Definition json.hpp:6523
@ bjdata
Definition json.hpp:6523
@ ubjson
Definition json.hpp:6523
@ json
Definition json.hpp:6523
@ cbor
Definition json.hpp:6523
@ msgpack
Definition json.hpp:6523
typename detector< nonesuch, void, Op, Args... >::type detected_t
Definition json.hpp:311
void to_json_tuple_impl(BasicJsonType &j, const Tuple &t, index_sequence< Idx... >)
Definition json.hpp:6104
decltype(T::to_json(std::declval< Args >()...)) to_json_function
Definition json.hpp:3643
detector< Default, void, Op, Args... > detected_or
Definition json.hpp:314
decltype(std::declval< T & >().binary(std::declval< Binary & >())) binary_function_t
Definition json.hpp:9731
typename std::conditional< is_usable_as_key_type< typename BasicJsonType::object_comparator_t, typename BasicJsonType::object_t::key_type, KeyTypeCVRef, RequireTransparentComparator, ExcludeObjectKeyType >::value &&!is_json_iterator_of< BasicJsonType, KeyType >::value, std::true_type, std::false_type >::type is_usable_as_basic_json_key_type
Definition json.hpp:4160
is_detected< string_can_append_data, StringType, Arg > detect_string_can_append_data
Definition json.hpp:4440
decltype(std::declval< T & >().end_object()) end_object_function_t
Definition json.hpp:9743
OutStringType concat(Args &&... args)
Definition json.hpp:4499
typename T::value_type value_type_t
Definition json.hpp:3628
constexpr std::array< T, sizeof...(Args)> make_array(Args &&... args)
Definition json.hpp:3346
JSON_HEDLEY_RETURNS_NON_NULL char * to_chars(char *first, const char *last, FloatType value)
generates a decimal representation of the floating-point number value in [first, last).
Definition json.hpp:18737
decltype(std::declval< T & >().boolean(std::declval< bool >())) boolean_function_t
Definition json.hpp:9711
std::is_same< Expected, detected_t< Op, Args... > > is_detected_exact
Definition json.hpp:320
is_detected< string_can_append, StringType, Arg > detect_string_can_append
Definition json.hpp:4422
typename std::enable_if< B, T >::type enable_if_t
Definition json.hpp:3219
parse_event_t
Definition json.hpp:12945
@ value
the parser finished reading a JSON value
Definition json.hpp:12957
@ key
the parser read a key of a value in an object
Definition json.hpp:12955
@ array_end
the parser read ] and finished processing a JSON array
Definition json.hpp:12953
@ array_start
the parser read [ and started to process a JSON array
Definition json.hpp:12951
@ object_start
the parser read { and started to process a JSON object
Definition json.hpp:12947
@ object_end
the parser read } and finished processing a JSON object
Definition json.hpp:12949
std::integral_constant< bool, all_signed< Types... >::value||all_unsigned< Types... >::value > same_sign
Definition json.hpp:4222
typename detector< nonesuch, void, Op, Args... >::value_t is_detected
Definition json.hpp:305
typename std::conditional< is_comparable< Comparator, ObjectKeyType, KeyTypeCVRef >::value &&!(ExcludeObjectKeyType &&std::is_same< KeyType, ObjectKeyType >::value) &&(!RequireTransparentComparator||is_detected< detect_is_transparent, Comparator >::value) &&!is_json_pointer< KeyType >::value, std::true_type, std::false_type >::type is_usable_as_key_type
Definition json.hpp:4142
typename T::pointer pointer_t
Definition json.hpp:3634
std::pair< A1, A2 > from_json_tuple_impl(BasicJsonType &&j, identity_tag< std::pair< A1, A2 > >, priority_tag< 0 >)
Definition json.hpp:5272
void from_json_array_impl(const BasicJsonType &j, typename BasicJsonType::array_t &arr, priority_tag< 3 >)
Definition json.hpp:5077
typename utility_internal::Gen< T, N >::type make_integer_sequence
Definition json.hpp:3307
conjunction< std::is_integral< Types >... > all_integral
Definition json.hpp:4212
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:15712
typename detected_or< Default, Op, Args... >::type detected_or_t
Definition json.hpp:317
decltype(std::declval< T & >().key(std::declval< String & >())) key_function_t
Definition json.hpp:9739
decltype(std::declval< T & >().null()) null_function_t
Definition json.hpp:9708
void int_to_string(StringType &target, std::size_t value)
Definition json.hpp:5469
T conditional_static_cast(U value)
Definition json.hpp:4200
typename T::difference_type difference_type_t
Definition json.hpp:3631
conjunction< std::is_unsigned< Types >... > all_unsigned
Definition json.hpp:4218
constexpr T static_const< T >::value
Definition json.hpp:3342
decltype(std::declval< T & >().start_object(std::declval< std::size_t >())) start_object_function_t
Definition json.hpp:9735
decltype(std::declval< T & >().number_float( std::declval< Float >(), std::declval< const String & >())) number_float_function_t
Definition json.hpp:9723
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:3095
decltype(std::declval< T & >().start_array(std::declval< std::size_t >())) start_array_function_t
Definition json.hpp:9746
is_detected< string_can_append_iter, StringType, Arg > detect_string_can_append_iter
Definition json.hpp:4434
auto get(const nlohmann::detail::iteration_proxy_value< IteratorType > &i) -> decltype(i.key())
Definition json.hpp:5651
typename std::conditional< is_detected< detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType >::value, std::true_type, std::false_type >::type has_erase_with_key_type
Definition json.hpp:4173
typename actual_object_comparator< BasicJsonType >::type actual_object_comparator_t
Definition json.hpp:3722
decltype(std::declval< ObjectType & >().erase(std::declval< KeyType >())) detect_erase_with_key_type
Definition json.hpp:4169
decltype(input_adapter(std::declval< const char * >(), std::declval< const char * >())) contiguous_bytes_input_adapter
Definition json.hpp:6977
bool little_endianness(int num=1) noexcept
determine system byte order
Definition json.hpp:9871
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9858
@ ignore
ignore tags
Definition json.hpp:9860
@ store
store tags as binary type
Definition json.hpp:9861
@ error
throw a parse_error exception in case of a tag
Definition json.hpp:9859
value_type_t< iterator_traits< iterator_t< T > > > range_value_t
Definition json.hpp:3897
make_index_sequence< sizeof...(Ts)> index_sequence_for
Definition json.hpp:3323
void concat_into(OutStringType &)
Definition json.hpp:4415
constexpr bool value_in_range_of(T val)
Definition json.hpp:4300
value_t
the JSON type enumeration
Definition json.hpp:2997
@ null
null value
Definition json.hpp:2998
@ number_integer
number value (signed integer)
Definition json.hpp:3003
@ boolean
boolean value
Definition json.hpp:3002
@ discarded
discarded by the parser callback function
Definition json.hpp:3007
@ binary
binary array (ordered collection of bytes)
Definition json.hpp:3006
@ object
object (unordered set of name/value pairs)
Definition json.hpp:2999
@ string
string value
Definition json.hpp:3001
@ number_float
number value (floating-point)
Definition json.hpp:3005
@ number_unsigned
number value (unsigned integer)
Definition json.hpp:3004
@ array
array (ordered collection of values)
Definition json.hpp:3000
decltype(T::from_json(std::declval< Args >()...)) from_json_function
Definition json.hpp:3646
conjunction< std::is_signed< Types >... > all_signed
Definition json.hpp:4215
constexpr std::size_t unknown_size()
Definition json.hpp:8837
std::array< T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType &&j, identity_tag< std::array< T, sizeof...(Idx)> >, index_sequence< Idx... >)
Definition json.hpp:5160
StringType to_string(std::size_t value)
Definition json.hpp:5477
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6364
decltype(std::declval< T & >().number_integer(std::declval< Integer >())) number_integer_function_t
Definition json.hpp:9715
void unescape(StringType &s)
string unescaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3129
typename make_void< Ts... >::type void_t
Definition json.hpp:266
std::size_t combine(std::size_t seed, std::size_t h) noexcept
Definition json.hpp:6346
decltype(std::declval< T & >().parse_error( std::declval< std::size_t >(), std::declval< const std::string & >(), std::declval< const Exception & >())) parse_error_function_t
Definition json.hpp:9753
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:3026
iterator_input_adapter_factory< IteratorType >::adapter_type input_adapter(IteratorType first, IteratorType last)
Definition json.hpp:6913
enable_if_t< is_range< R >::value, result_of_begin< decltype(std::declval< R & >())> > iterator_t
Definition json.hpp:3894
typename T::iterator_category iterator_category_t
Definition json.hpp:3640
typename std::conditional< std::is_same< T, void >::value, json_default_base, T >::type json_base_class
Definition json.hpp:14542
is_c_string< uncvref_t< T > > is_c_string_uncvref
Definition json.hpp:4334
error_handler_t
how to treat decoding errors
Definition json.hpp:18817
@ strict
throw a type_error exception in case of invalid UTF-8
Definition json.hpp:18818
@ ignore
ignore invalid UTF-8 sequences
Definition json.hpp:18820
@ replace
replace invalid UTF-8 sequences with U+FFFD
Definition json.hpp:18819
std::size_t concat_length()
Definition json.hpp:4384
std::integral_constant< bool, Value > bool_constant
Definition json.hpp:4306
decltype(input_adapter(std::declval< std::string >())) string_input_adapter_type
Definition json.hpp:6953
typename std::remove_cv< typename std::remove_reference< T >::type >::type uncvref_t
Definition json.hpp:3205
void from_json(const BasicJsonType &j, typename std::nullptr_t &n)
Definition json.hpp:4857
typename T::key_compare detect_key_compare
Definition json.hpp:3706
void to_json(BasicJsonType &j, T b) noexcept
Definition json.hpp:5965
void get_arithmetic_value(const BasicJsonType &j, ArithmeticType &val)
Definition json.hpp:4886
integer_sequence< size_t, Ints... > index_sequence
Definition json.hpp:3261
std::is_convertible< detected_t< Op, Args... >, To > is_detected_convertible
Definition json.hpp:323
is_specialization_of<::nlohmann::json_pointer, uncvref_t< T > > is_json_pointer
Definition json.hpp:4123
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().begin(), std::declval< const Arg & >().end())) string_can_append_iter
Definition json.hpp:4431
decltype(std::declval< T & >().end_array()) end_array_function_t
Definition json.hpp:9750
std::tuple< Args... > from_json_tuple_impl_base(BasicJsonType &&j, index_sequence< Idx... >)
Definition json.hpp:5260
decltype(std::declval< StringType & >().append(std::declval< const Arg & >().data(), std::declval< const Arg & >().size())) string_can_append_data
Definition json.hpp:4437
typename T::key_type key_type_t
Definition json.hpp:3625
typename T::reference reference_t
Definition json.hpp:3637
typename T::is_transparent detect_is_transparent
Definition json.hpp:4136
bjdata_version_t
how to encode BJData
Definition json.hpp:15825
@ draft3
Definition json.hpp:15827
@ draft2
Definition json.hpp:15826
is_detected< string_can_append_op, StringType, Arg > detect_string_can_append_op
Definition json.hpp:4428
typename T::mapped_type mapped_type_t
Definition json.hpp:3622
decltype(std::declval< StringType & >()+=std::declval< Arg && >()) string_can_append_op
Definition json.hpp:4425
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3114
decltype(std::declval< T & >().string(std::declval< String & >())) string_function_t
Definition json.hpp:9727
decltype(std::declval< T >().template get< U >()) get_template_function
Definition json.hpp:3649
decltype(std::declval< T & >().number_unsigned(std::declval< Unsigned >())) number_unsigned_function_t
Definition json.hpp:9719
std::function< bool(int, parse_event_t, BasicJsonType &)> parser_callback_t
Definition json.hpp:12961
Definition json.hpp:25278
Definition json.hpp:25276
Definition json.hpp:5672
NLOHMANN_BASIC_JSON_TPL_DECLARATION void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL &j1, nlohmann::NLOHMANN_BASIC_JSON_TPL &j2) noexcept(//NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp) is_nothrow_move_constructible< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value &&//NOLINT(misc-redundant-expression, cppcoreguidelines-noexcept-swap, performance-noexcept-swap) is_nothrow_move_assignable< nlohmann::NLOHMANN_BASIC_JSON_TPL >::value)
exchanges the values of two JSON objects
Definition json.hpp:25351
namespace for Niels Lohmann
Definition json.hpp:6175
static auto to_json(BasicJsonType &j, TargetType &&val) noexcept(noexcept(::nlohmann::to_json(j, std::forward< TargetType >(val)))) -> decltype(::nlohmann::to_json(j, std::forward< TargetType >(val)), void())
convert any value type to a JSON value
Definition json.hpp:6199
static auto from_json(BasicJsonType &&j) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), detail::identity_tag< TargetType > {}))
convert a JSON value to any value type
Definition json.hpp:6189
static auto from_json(BasicJsonType &&j, TargetType &val) noexcept(noexcept(::nlohmann::from_json(std::forward< BasicJsonType >(j), val))) -> decltype(::nlohmann::from_json(std::forward< BasicJsonType >(j), val), void())
convert a JSON value to any value type
Definition json.hpp:6179
Definition json.hpp:3714
typename BasicJsonType::object_t object_t
Definition json.hpp:3715
typename BasicJsonType::default_object_comparator_t object_comparator_t
Definition json.hpp:3716
typename std::conditional< has_key_compare< object_t >::value, typename object_t::key_compare, object_comparator_t >::type type
Definition json.hpp:3717
signed char char_type
Definition json.hpp:3761
static constexpr int_type eof() noexcept
Definition json.hpp:3775
uint64_t int_type
Definition json.hpp:3762
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3770
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3765
static char_type to_char_type(int_type i) noexcept
Definition json.hpp:3746
static constexpr int_type eof() noexcept
Definition json.hpp:3751
unsigned char char_type
Definition json.hpp:3737
uint64_t int_type
Definition json.hpp:3738
static int_type to_int_type(char_type c) noexcept
Definition json.hpp:3741
Definition json.hpp:3731
Definition json.hpp:3810
decltype(input_adapter(begin(std::declval< ContainerType >()), end(std::declval< ContainerType >()))) adapter_type
Definition json.hpp:6936
Definition json.hpp:292
std::false_type value_t
Definition json.hpp:293
Default type
Definition json.hpp:294
Definition json.hpp:17848
diyfp w
Definition json.hpp:17849
diyfp minus
Definition json.hpp:17850
diyfp plus
Definition json.hpp:17851
Definition json.hpp:17987
std::uint64_t f
Definition json.hpp:17988
int e
Definition json.hpp:17989
int k
Definition json.hpp:17990
Definition json.hpp:17730
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:17754
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:17836
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17819
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:17742
constexpr diyfp(std::uint64_t f_, int e_) noexcept
Definition json.hpp:17736
static constexpr int kPrecision
Definition json.hpp:17731
std::uint64_t f
Definition json.hpp:17733
int e
Definition json.hpp:17734
static void construct(BasicJsonType &j, const std::vector< bool > &arr)
Definition json.hpp:5874
static void construct(BasicJsonType &j, typename BasicJsonType::array_t &&arr)
Definition json.hpp:5849
static void construct(BasicJsonType &j, const typename BasicJsonType::array_t &arr)
Definition json.hpp:5839
static void construct(BasicJsonType &j, const CompatibleArrayType &arr)
Definition json.hpp:5861
static void construct(BasicJsonType &j, const std::valarray< T > &arr)
Definition json.hpp:5890
static void construct(BasicJsonType &j, const typename BasicJsonType::binary_t &b)
Definition json.hpp:5778
static void construct(BasicJsonType &j, typename BasicJsonType::binary_t &&b)
Definition json.hpp:5787
static void construct(BasicJsonType &j, typename BasicJsonType::boolean_t b) noexcept
Definition json.hpp:5732
static void construct(BasicJsonType &j, typename BasicJsonType::number_float_t val) noexcept
Definition json.hpp:5800
static void construct(BasicJsonType &j, typename BasicJsonType::number_integer_t val) noexcept
Definition json.hpp:5826
static void construct(BasicJsonType &j, typename BasicJsonType::number_unsigned_t val) noexcept
Definition json.hpp:5813
static void construct(BasicJsonType &j, const typename BasicJsonType::object_t &obj)
Definition json.hpp:5909
static void construct(BasicJsonType &j, const CompatibleObjectType &obj)
Definition json.hpp:5930
static void construct(BasicJsonType &j, typename BasicJsonType::object_t &&obj)
Definition json.hpp:5919
static void construct(BasicJsonType &j, typename BasicJsonType::string_t &&s)
Definition json.hpp:5754
static void construct(BasicJsonType &j, const CompatibleStringType &str)
Definition json.hpp:5765
static void construct(BasicJsonType &j, const typename BasicJsonType::string_t &s)
Definition json.hpp:5745
Definition json.hpp:5726
Definition json.hpp:5369
auto operator()(const BasicJsonType &j, T &&val) const noexcept(noexcept(from_json(j, std::forward< T >(val)))) -> decltype(from_json(j, std::forward< T >(val)))
Definition json.hpp:5371
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3668
Definition json.hpp:3653
Definition json.hpp:3709
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3683
Definition json.hpp:3678
typename BasicJsonType::template json_serializer< T, void > serializer
Definition json.hpp:3698
Definition json.hpp:3693
Definition json.hpp:4799
Definition json.hpp:3247
T value_type
Definition json.hpp:3248
static constexpr std::size_t size() noexcept
Definition json.hpp:3249
an iterator value
Definition json.hpp:13591
BasicJsonType::array_t::iterator array_iterator
iterator for JSON arrays
Definition json.hpp:13595
primitive_iterator_t primitive_iterator
generic iterator for all other types
Definition json.hpp:13597
BasicJsonType::object_t::iterator object_iterator
iterator for JSON objects
Definition json.hpp:13593
Definition json.hpp:3602
Definition json.hpp:3589
Definition json.hpp:4331
Definition json.hpp:4127
Definition json.hpp:4010
Definition json.hpp:4081
Definition json.hpp:3931
Definition json.hpp:3968
static constexpr auto value
Definition json.hpp:3969
Definition json.hpp:4084
Definition json.hpp:4097
Definition json.hpp:3904
Definition json.hpp:4054
Definition json.hpp:3964
Definition json.hpp:3975
ConstructibleStringType laundered_type
Definition json.hpp:3980
static constexpr auto value
Definition json.hpp:3983
Definition json.hpp:4100
Definition json.hpp:3842
Definition json.hpp:3823
Definition json.hpp:308
Definition json.hpp:3661
static constexpr bool value
Definition json.hpp:3662
Definition json.hpp:6889
typename std::iterator_traits< T >::value_type value_type
Definition json.hpp:6890
static constexpr auto value
Definition json.hpp:3866
Definition json.hpp:3857
Definition json.hpp:4106
Definition json.hpp:3612
Definition json.hpp:4188
char x[2]
Definition json.hpp:4189
Definition json.hpp:4184
@ value
Definition json.hpp:4195
static one test(decltype(&C::capacity))
char one
Definition json.hpp:4185
static two test(...)
Definition json.hpp:3876
static constexpr bool value
Definition json.hpp:3890
Definition json.hpp:9790
Definition json.hpp:9759
static constexpr bool value
Definition json.hpp:9772
Definition json.hpp:4117
Definition json.hpp:4353
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6901
wide_string_input_adapter< base_adapter_type, char_type > adapter_type
Definition json.hpp:6903
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6905
iterator_input_adapter< iterator_type > adapter_type
Definition json.hpp:6879
typename std::iterator_traits< iterator_type >::value_type char_type
Definition json.hpp:6878
static adapter_type create(IteratorType first, IteratorType last)
Definition json.hpp:6881
IteratorType iterator_type
Definition json.hpp:6877
std::random_access_iterator_tag iterator_category
Definition json.hpp:3429
Definition json.hpp:3417
Definition json.hpp:3398
Default base class of the basic_json class.
Definition json.hpp:14539
Definition json.hpp:263
void type
Definition json.hpp:264
Definition json.hpp:3817
Definition json.hpp:278
nonesuch(nonesuch const &&)=delete
~nonesuch()=delete
void operator=(nonesuch &&)=delete
void operator=(nonesuch const &)=delete
nonesuch(nonesuch const &)=delete
abstract output adapter interface
Definition json.hpp:15698
output_adapter_protocol(const output_adapter_protocol &)=default
virtual ~output_adapter_protocol()=default
virtual void write_character(CharType c)=0
output_adapter_protocol(output_adapter_protocol &&) noexcept=default
virtual void write_characters(const CharType *s, std::size_t length)=0
struct to capture the start position of the current token
Definition json.hpp:3160
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3164
std::size_t lines_read
the number of lines read
Definition json.hpp:3166
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3162
Definition json.hpp:3330
Definition json.hpp:3336
static JSON_INLINE_VARIABLE constexpr T value
Definition json.hpp:3337
Definition json.hpp:6142
auto operator()(BasicJsonType &j, T &&val) const noexcept(noexcept(to_json(j, std::forward< T >(val)))) -> decltype(to_json(j, std::forward< T >(val)), void())
Definition json.hpp:6144
integer_sequence< T, Ints...,(Ints+SeqSize)... > type
Definition json.hpp:3273
integer_sequence< T, Ints...,(Ints+SeqSize)..., 2 *SeqSize > type
Definition json.hpp:3279
Definition json.hpp:3267
integer_sequence< T > type
Definition json.hpp:3294
Definition json.hpp:3286
typename Extend< typename Gen< T, N/2 >::type, N/2, N % 2 >::type type
Definition json.hpp:3287
static constexpr bool test(T val)
Definition json.hpp:4284
static constexpr bool test(T)
Definition json.hpp:4293
Definition json.hpp:4279
static constexpr bool test(T val)
Definition json.hpp:4238
static constexpr bool test(T val)
Definition json.hpp:4258
static constexpr bool test(T val)
Definition json.hpp:4248
static constexpr bool test(T val)
Definition json.hpp:4268
Definition json.hpp:4233
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6764
static void fill_buffer(BaseInputAdapter &input, std::array< std::char_traits< char >::int_type, 4 > &utf8_bytes, size_t &utf8_bytes_index, size_t &utf8_bytes_filled)
Definition json.hpp:6706
Definition json.hpp:6700
SAX interface.
Definition json.hpp:8722
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
json_sax()=default
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
typename BasicJsonType::number_integer_t number_integer_t
Definition json.hpp:8723
typename BasicJsonType::string_t string_t
Definition json.hpp:8726
virtual bool end_array()=0
the end of an array was read
json_sax(const json_sax &)=default
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
typename BasicJsonType::number_float_t number_float_t
Definition json.hpp:8725
virtual bool null()=0
a null value was read
typename BasicJsonType::number_unsigned_t number_unsigned_t
Definition json.hpp:8724
json_sax(json_sax &&) noexcept=default
typename BasicJsonType::binary_t binary_t
Definition json.hpp:8727
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19799
std::vector< std::pair< const Key, T >, Allocator > Container
Definition json.hpp:19802
std::pair< iterator, bool > insert(value_type &&value)
Definition json.hpp:20093
typename Container::value_type value_type
Definition json.hpp:19806
std::equal_to< Key > key_compare
Definition json.hpp:19810
iterator erase(iterator pos)
Definition json.hpp:19971
T mapped_type
Definition json.hpp:19801
ordered_map(const Allocator &alloc) noexcept(noexcept(Container(alloc)))
Definition json.hpp:19816
T & operator[](KeyType &&key)
Definition json.hpp:19858
typename Container::iterator iterator
Definition json.hpp:19803
const T & at(KeyType &&key) const
Definition json.hpp:19918
T & at(KeyType &&key)
Definition json.hpp:19890
const T & operator[](KeyType &&key) const
Definition json.hpp:19870
iterator find(const key_type &key)
Definition json.hpp:20055
iterator erase(iterator first, iterator last)
Definition json.hpp:19976
const T & at(const key_type &key) const
Definition json.hpp:19903
const_iterator find(const key_type &key) const
Definition json.hpp:20081
T & operator[](const key_type &key)
Definition json.hpp:19851
size_type erase(KeyType &&key)
Definition json.hpp:19952
typename Container::size_type size_type
Definition json.hpp:19805
ordered_map() noexcept(noexcept(Container()))
Definition json.hpp:19815
void insert(InputIt first, InputIt last)
Definition json.hpp:20116
size_type count(const key_type &key) const
Definition json.hpp:20029
std::pair< iterator, bool > emplace(KeyType &&key, T &&t)
Definition json.hpp:19838
typename std::enable_if< std::is_convertible< typename std::iterator_traits< InputIt >::iterator_category, std::input_iterator_tag >::value >::type require_input_iter
Definition json.hpp:20112
size_type erase(const key_type &key)
Definition json.hpp:19931
ordered_map(std::initializer_list< value_type > init, const Allocator &alloc=Allocator())
Definition json.hpp:19820
std::pair< iterator, bool > insert(const value_type &value)
Definition json.hpp:20098
size_type count(KeyType &&key) const
Definition json.hpp:20043
Key key_type
Definition json.hpp:19800
ordered_map(It first, It last, const Allocator &alloc=Allocator())
Definition json.hpp:19818
const T & operator[](const key_type &key) const
Definition json.hpp:19863
iterator find(KeyType &&key)
Definition json.hpp:20069
T & at(const key_type &key)
Definition json.hpp:19875
typename Container::const_iterator const_iterator
Definition json.hpp:19804
std::pair< iterator, bool > emplace(const key_type &key, T &&t)
Definition json.hpp:19823
std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL &j) const
Definition json.hpp:25320
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:25334
nlohmann::json json
Definition tiingo_client.cpp:16